Reputation: 362
I am new to the NASM assembler, and have attempted to write my own assembly code. Upon compiling, I have not received any errors, but on runtime, the code crashes. While debugging, it seems that the code is crashing at either the push or _printf calls.
I've commented my code to make it a bit more readable.
global _main
extern _printf
section .text
_main:
jp _loop ;jump to loop
_loop:
mov ebx, [a] ;move double word 'a' into register ebx
inc ebx ;increment register ebx
mov [a], ebx ;move contents of ebx into double word 'a'
add ebx, '0' ;add char 0 (0x30)
push ebx ;push ascii character on to stack
push format ;push format string on to stack
call _printf ;call print function
cmp dword [a], 10 ;compare if value of a is equal to 10
jne _loop ;loop if not equal to 10
ret ;return if equal to 10
a:
dd 0 ;initialize dword as 0
format:
db "%i", 0 ;format string for printf
Thanks in advance! I hope this isn't too nooby.
Upvotes: 2
Views: 205
Reputation: 129119
I tried compiling and running your code myself (alas not on Windows; who says assembly isn’t portable?), and it crashed not on the call _printf
or push
lines, but on mov [a], ebx
. The permissions on the .text
segment are read and execute, but not write. a
is in .text
, and mov [a], ebx
tries to write to a
, so it tries to write to a non-writable section, and the program crashes with a general protection fault. The way you’d get around this is by putting a
in a different section, e.g. .data
.
That should solve your (first) problem, but there’s two more things you ought to know about:
You have jp _loop
as the first instruction of _main
. That jumps to _loop
if the parity flag is set. I don’t think you actually meant to test the parity flag; in this case, it either jumps there, or the test fails and it falls through to _loop
anyway. You could do an explicit jmp
, but it’s really not necessary. If I were you, I’d just omit that instruction entirely so _main
and _loop
coincide.
I believe _printf
uses the C calling convention, where the caller is responsible for popping the arguments (unlike the stdcall used for Windows API functions); you’re pushing lots of things onto the stack, and never popping them. That means the more iterations you do, the more stack memory you’re using. That doesn’t seem like what you want. Furthermore, you later ret
, which, since you pushed things in the mean time, won’t return to the right place since the top of the stack isn’t the return address. You’ll want to pop or adjust the stack pointer explicitly after calling _printf
:
add esp, 8
Alternatively:
Before your loop, reserve the appropriate amount of stack space:
sub esp, 8
After your loop, release that stack space:
add esp, 8
Rather than pushing arguments, modify the data already on the stack:
mov [esp+4], ebx
mov [esp], format
Upvotes: 2