0

I am a beginner in Assembly Language Programming and I am looking for some help in creating a for loop that runs in n/10 seconds.

I am having trouble understanding how I would convert this Java for loop into an assembly language for loop. N is a value that user enters. for(i = 1; i<= n; i++)

Am I heading in the right direction? And if I am not where am I making a mistake? I am just trying to get the loop working and I will worry about run time later.

CODE:

.586
.MODEL FLAT

INCLUDE io.h            ; header file for input/output

.STACK 4096

.DATA

number1 DWORD   ?

sum DWORD   ?

prompt1 BYTE    "Enter a number between 1-100", 0

string  BYTE    40 DUP (?)

.CODE

_MainProc PROC

    input   prompt1, string, 40      ; read ASCII characters
    atod    string          ; convert to integer
    mov     ecx, eax    ; store input to memory this is n
    mov     eax, 0  ; //set eax to 0
    mov     edx, 0  //This is sum
    mov ebx, 1      //Create i
    cmp ecx, ebx    //compare i to n
    jnle ecx        //jump when negative or less than ecx
    add edx, ebx    //adds i to sum
    inc ebx         //i++
    jmp ebx         //jump to ebx repeat
_MainProc ENDP

END                             ; end of source code
Cheerios
  • 15
  • 1
  • 7
  • What the hell? A fixed amount of real time like `n/10` seconds is a totally different question from a fixed iteration count (running `n/10` times like the title says). CPUs have variable clock speeds... – Peter Cordes Nov 08 '17 at 01:39
  • Your edit totally changed the question. If you want to break out of a loop after n tenths of a second, you could check `rdtsc` every 100 iterations, or set a timer that will run a signal handler which changes a variable. If you just want to delay, sleep with a `nanosleep` system call or whatever the Windows equivalent is. You should avoid using a delay loop for anything longer than a microsecond or so. – Peter Cordes Nov 08 '17 at 03:59

1 Answers1

0

The easiest way to loop by a fraction of something is to add or sub by 10 in the loop.

Instead of doing a division to get the iteration count, do repeated subtraction inside the loop. Repeated add/sub is normally a terrible way to multiply/divide, but you want to loop that many times anyway so you use that as the loop counter. This is called a "strength reduction" optimization, because division is "stronger" (slower/more expensive) than subtraction.

One way to do this is to count down towards zero and break out of the loop when the counter becomes negative (signed less-than), or alternatively when it crosses zero (unsigned carry).

atod returns the result in eax so you're clobbering it with mov eax, 0.

    ... code to get input, and call atod
    ; atod return value in eax = n

    xor    edx, edx       ; sum = edx = 0

    ; loop n/10 times  (integer division truncates towards 0)
@loop:                    ; do {
    add    edx, eax         ; sum += i

    sub    eax, 10          ; i -= 10
    jnc    @loop          ; } while(i didn't wrap around);

    mov    eax, edx      ; eax=sum

Or use jg to loop }while(i>0), or jge to loop }while(i>=0). Adding zero is a no-op, so we can let the loop run once when i=0, but jg would be good here if you don't need to support a starting value greater than the largest signed 32-bit integer. (i.e. if you don't need unsigned).

If you want to loop upwards, you can do that with a compare-and-branch

    ... code to get input, and call atod
    ; atod return value in eax = n

    xor    edx, edx       ; sum = edx = 0
    mov    ecx, 1         ;   i = ecx = 1

    ; if the loop might need to run 0 times, test eax,eax / jz to the bottom.
    ; or cmp eax, 10 or whatever.
@loop:                    ; do {
    add    edx, ecx         ; sum += i

    add    ecx, 10          ; i += 10
    cmp    ecx, eax
    jb     @loop          ; } while(i < n);

    mov    eax, edx      ; eax=sum

Adjust as desired to do a signed compare, or jbe to do <=, or whatever.

in big o notation of n/10.

O(n) complexity classes don't count constant factors, so O(n) = O(n/10). I'm assuming you mean "runs n/10 times" like you said in the title, not n times like in your Java for loop, or O(n) times (which would allow any off-by-one errors or constant multipliers).


If you want a counter that only increments by 1 in the loop, you could count down the loop-terminating condition (towards zero) and count up another register. Your Java didn't show the factor of 10 anywhere so IDK where you want it.

Avoid using div if possible, it's about 30x slower than add.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847