According to this paper and a few stackoverflow posts, argc is at the top of the stack and argv is below it.
I've tried about 3-4 different ways of doing it:
printf
.sys_write()
I've been told that argc and argv aren't in the stack by someone on a forum, which I don't understand; how are other people doing it with similar code?
Here's an example of what I've attempted (3 days worth of knowledge - try not to giggle):
section .bss
argc: resd 1 ; alloc 4 bytes for popped value
section .text
global _start
_start:
pop dword[argc] ; pop argc, place in var
mov ebx,0x01 ; file descriptor = STDOUT
mov ecx,argc ; var (addr) - points to buffer
mov edx,1 ; length of buffer (single digit)
mov eax,0x04 ; syscall number for sys_write()
int 0x80 ; request the kernel to make syscall
exit:
mov ebx,0x00 ; arg for sys_exit() - sys_exit(0)
mov eax,0x01 ; syscall number for sys_exit()
int 0x80 ; request the kernel to make syscall
Solution:
section .data
msg db Value: %d\n
section .text
global main
extern printf
main:
push dword[esp+4]
push msg
call printf
add esp,8
mov eax,0
ret
The process of getting argc
looks ok to me (for a 32-bit Linux machine), although you're 4 bytes off since the top of the stack most likely contains the return address to the startup code that called main
.
Also, the sys_write
system call expects a pointer to a string in ecx
. What you're giving it is a pointer to an integer, which isn't the same thing.
If you want to print the value of argc
you'll have to convert it to a string first (or use the printf
function).
Here's some example code (I'm using the GNU assembler since I don't have NASM on this machine):
format: .asciz "%d\n"
.text
.globl main
.type main, @function
main:
pushl 4(%esp) # push argc
pushl $format # push the format string
call printf
addl $8,%esp # pop the arguments
movl $0, %eax # return value
ret