3
\$\begingroup\$

Assignment:

Write a program which reads a number n from the console. Then calculates the sum of all odd numbers between 1 and 2n + 1 (incl.).

Assignment also on GitHub, Exercise 0.0.

The functions read_hex and print_eax as well as the header and tail of the script are provided by the tutor.

format PE console
entry start

include 'win32a.inc' 

; ===============================================
section '.text' code readable executable

start:
    call    read_hex

    mov     esi, 1 ; esi becomes the counting variable.

    mov     ebx, 2
    mul     ebx
    add     eax, 2
    mov     edi, eax ; edi becomes the limit.

    mov     eax, esi    
    mov     ebx, 2 ; Will be the divisor.   
    mov     ecx, 0 ; ecx will store the sum.
operationSet:
    mov edx, 0 ; Make sure that the register is empty.
    div ebx

    cmp edx, 0
    JE manageOperationSet ; If 0 then skip next operation.
    add ecx, esi   
manageOperationSet:
    inc esi
    mov eax, esi
    cmp esi, edi
    jne operationSet

    mov eax, ecx
    call print_eax

    push    0
    call    [ExitProcess]    
include 'training.inc'

I've tested my program with the numbers from 1 to 6 and get correct results. I think it works correctly, but I'm not sure concerning my register usage.

Moreover: What could be improved? Are there weak points in my code?

\$\endgroup\$
6
  • \$\begingroup\$ Do I understand your code correctly that you iterate over all the numbers? \$\endgroup\$ – I'll add comments tomorrow Sep 10 '16 at 10:16
  • \$\begingroup\$ Yep. I calc (enteredNumber * 2 + 2) => Becomes the limit. 2 because it's said: n * 2 + 1 (inclusive). If my counting variable has reached the limit I don't enter the loop again. \$\endgroup\$ – michael.zech Sep 10 '16 at 10:27
  • 2
    \$\begingroup\$ I believe you have a bug in your code. You are summing all numbers between 1 and 2N +1 where it should be all ODD numbers based on the problem statement. You are adding too many numbers. You need to skip all numbers where i%2 == 0. You need to fix the code or it is off topic. \$\endgroup\$ – pacmaninbw Sep 10 '16 at 14:19
  • \$\begingroup\$ I disagree with you. Had a look at the official solution for the exercise: github.com/xorpd/asm_prog_ex/blob/master/4_basic_assembly/… Tested once more with 1, 2 and 4. My implementation is different from the solution but I get the same results: 4, 9 and 19 (25). \$\endgroup\$ – michael.zech Sep 11 '16 at 7:26
  • 1
    \$\begingroup\$ some asm tricks: 1) to zero some register you can use xor r,r but it will destroy some flags also, so not to be done after some compare. 2) to non-destructive test whether value is even; you can do test r,1. This will mask out everything except the lowest bit: when set (ZF=0 after test), the value is odd. When the lowest bit is zero, ZF will be ON after test, indicating even value. You could also considered to simply start at 1 and add two every step. Before coding try to simplify the algorithm a bit, that direct formula from David is advanced, but += 2 is sort of basic level. \$\endgroup\$ – Ped7g Sep 12 '16 at 13:34
7
\$\begingroup\$

Random thoughts:

  • A comment that indicates what/where read_hex returns might be useful.
  • mov ebx, 2; mul ebx could probably be replaced with shl eax,1.
  • While div can be used to check for 'oddness', I believe it is an expensive solution. How about bt?
  • In fact, why check for oddness every iteration of the loop? Check once at the top and count by 2's.
  • If you aren't using mul/div, then you don't have to have values in specific registers. This might help you avoid moving values from one register to another so much.

But my biggest piece of advice is to junk this whole approach and start over.

I've tried to calculate some solutions here (let me know if I've got this wrong):

n   result
0   1
1   4
2   9
3   16
4   25

Do you notice anything interesting about the numbers in the right-hand column? Here's a hint, but before you hover over it, take a moment to try to puzzle it out yourself. You'll feel better if you do.

1*1 = 1, 2 * 2 = 4, 3 * 3 = 9, 4*4 = 16, 5 * 5 = 25

Or in other words:

(n+1)2

With that in mind, there's a much faster/simpler way to calculate results, especially if n is big.

\$\endgroup\$
2
  • \$\begingroup\$ @user2023861 Agreed. I can see how the general idea makes a good beginner's tutorial: Looping, conditions, summing, etc. But it's also a good sample to show that you need to keep thinking about what you are trying to accomplish and not get too wrapped up in your first approach. I tried to address both. \$\endgroup\$ – David Wohlferd Sep 12 '16 at 18:55
  • \$\begingroup\$ Thanks for the great tipps. :) Haven't known the instructions you mentioned because the haven't been part of my course (yet). Learnt a lot from your answer. \$\endgroup\$ – michael.zech Sep 13 '16 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.