我尝试使用nasm:
打印给我程序的命令行参数GLOBAL main
EXTERN printf
section .rodata
fmt db "Argument: %s", 10, 0
section .text
main:
push ebp ; push ebp0
mov ebp, esp ; [ebp1] == ebp0
push dword[ebp+8] ; push argc
call print_args
mov eax, 0 ; return(0)
mov esp, ebp ; pop
pop ebp ; stack frame
ret
print_args:
push ebp ; pusheo ebp1
mov ebp, esp ; [ebp2] == ebp1
mov edi, dword[ebp+8] ; [ebp+8] == argc
jmp lop
postlop:
mov esp, ebp
pop ebp
ret
lop:
sub edi, 1
cmp edi, 0
jz postlop
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv[0]?
push ebx
push fmt
call printf
jmp lop
但是,这只打印垃圾(我相信这应该打印argv[0]
,argc-1
次。)。
我用以下代码编译我的代码:
nasm -f elf32 main.asm
gcc -m32 main.o -o main.out
有什么问题?
顺便说一句,使用 dword[ebp+8]
可以正常使用 argc
。
我在ubuntu上运行它。程序会输出Argument: ...
argc-1
次,但...
是垃圾。
答案 0 :(得分:2)
就像[epb+8]
是argc
,[esi + 12]
是argv
,即 数组的地址论证地址。因此,为了找到argv[0]
,您必须再次取消引用。
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv
push dword [ebx] ; [ebx] = argv[0]
;^^^^^^^^^^^
push fmt
call printf
答案 1 :(得分:0)
我已经完成了,这就是您所需要的
如此组装。在我的32位Debian 9 VM上:
$ nasm -felf32 -g args.s -o args.o
$ gcc -no-pie args.o -o args
segment .data
format db "%s",0x0a,0
segment .text
global main ; let the linker know about main
extern printf ; resolve printf from libc
main:
push ebp ; prepare stack frame for main
mov ebp, esp
sub esp, 8
mov edi, dword[ebp+8] ; get argc into edi
mov esi, dword[ebp+12] ; get first argv string into esi
start_loop:
xor eax, eax
push dword [esi] ; must dereference esi; points to argv
push format
call printf
add esi, 4 ; advance to the next pointer in argv
dec edi ; decrement edi from argc to 0
cmp edi, 0 ; when it hits 0, we're done
jnz start_loop ; end with NULL pointer
end_loop:
xor eax, eax
leave
ret