Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

NASM Why is this loop never ending?

assembly kernel

Best Answer Poe, 16 October 2014 - 10:10 AM

EDIT: For Once Dargueta didn't solve it for me (well, I guess he hinted towards it) a sign I am becoming better at low level programming!

 

I have figured it out, CX is a 16 bit loop register (or at least can be used as such):

TERMINAL:

	cmp cx,10
	je ENDSEC
	
	add cx,1
	
	mov SI,Before
	CALL PRINTSTR
	jmp TERMINAL
	
ENDSEC:

	ret
Go to the full post


This topic has been archived. This means that you cannot reply to this topic.
5 replies to this topic

#1 Poe

Poe

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 81 posts

Posted 15 October 2014 - 09:48 PM

TERMINAL:

	cmp eax,10
	je ENDSEC
	
	add eax,1
	
	mov SI,String
	CALL PRINTSTR
	jmp TERMINAL
	
ENDSEC:

	ret

ok so I have a problem, this is without an OS (its a bootable program) and it works good for printing to screen so far.

However i'm just learning assembler, but to me it seems this should loop to 10 showing the String each time and then end, however it shows the String in a never ending loop that eventually crashes my computer.

 

Anyone care to tell me what i've done wrong?


"Portability is for those who can't write new programs" - Linus Torvalds


#2 Alexander

Alexander

    YOL9

  • Moderator
  • 3963 posts

Posted 16 October 2014 - 01:11 AM

Some general programmer's thoughts: Is eax ever initialised? If it starts at, say, 42, it may never increment to 10. Is eax respected every iteration, or does PRINTSTR or something behind the scenes use that register? It might be a good idea to step through that with a debugger (outside of your OS), and, if so, utilise the stack for this passive variable and pop it at the beginning of the loop.

 

Alexander.


Edited by Alexander, 16 October 2014 - 01:54 AM.

All new problems require investigation, and so if errors are problems, try to learn as much as you can and report back.


#3 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 16 October 2014 - 09:37 AM

In general, one cannot expect eax, ecx, and edx to be preserved across calls to functions in 32-bit code. It's a standard calling convention.

 

Edit: Try changing je to jna just for shiggles.


Edited by dargueta, 16 October 2014 - 09:40 AM.

sudo rm -rf / && echo $'Sanitize your inputs!'


#4 Poe

Poe

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 81 posts

Posted 16 October 2014 - 09:55 AM

In general, one cannot expect eax, ecx, and edx to be preserved across calls to functions in 32-bit code. It's a standard calling convention.

 

Edit: Try changing je to jna just for shiggles.

changing je to jna doesn't loop, I looked used 16 bit registers (as I haven't even moved into 32 bit yet) however I get the same problem.

 

If the register doesn't always have a continuous value how would I go about a loop?

Heres the full code:

[BITS 16]
[ORG 0x7C00]

start:

	mov SI,Hello
	CALL PRINTSTR

	mov ah,0
	CALL TERMINAL
	
	jmp $

TERMINAL:

	;pop eax
	cmp ah,10
	jna ENDSEC
	
	add ah,1
	
	mov SI,Before
	CALL PRINTSTR
	jmp TERMINAL
	
ENDSEC:

	ret

PRINTCHAR:

    mov ah, 0x0E    ; Teletype output mode
    mov bh, 0x00    ; Page number
    mov bl, 0x0A    ; Grey font
    int 0x10        ; Call video interrupt
    ret             ; Return to the calling procedure

PRINTSTR:

    lodsb           ; Load a byte from SI to AL and increment SI
    cmp al, 0       ; Compare accumulator to 0
    je EXIT         ; If AL == 0, call the EXIT procedure
    call PRINTCHAR  ; Else, print the current character on the screen
    jmp PRINTSTR    ; Jump to PRINTSTR - print the rest of the string

EXIT:

    ret             ; Just return
    
Hello DB 'Loading System...', 13, 10, 0
Input DB 'Test'
Before DB '#', 13, 10, 0
	
times 510 - ($ - $$) DB 0
dw 0xAA55

"Portability is for those who can't write new programs" - Linus Torvalds


#5 Poe

Poe

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 81 posts

Posted 16 October 2014 - 10:10 AM   Best Answer

EDIT: For Once Dargueta didn't solve it for me (well, I guess he hinted towards it) a sign I am becoming better at low level programming!

 

I have figured it out, CX is a 16 bit loop register (or at least can be used as such):

TERMINAL:

	cmp cx,10
	je ENDSEC
	
	add cx,1
	
	mov SI,Before
	CALL PRINTSTR
	jmp TERMINAL
	
ENDSEC:

	ret

Edited by Poe, 16 October 2014 - 10:12 AM.

"Portability is for those who can't write new programs" - Linus Torvalds


#6 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 16 October 2014 - 03:41 PM

Um, no. You can't trust the BIOS to restore any registers to their original values (and in fact for the sake of speed most won't). The safest way to solve this would be:

push    ax
call    PRINTSTR
pop     ax

sudo rm -rf / && echo $'Sanitize your inputs!'





Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download