使用nasm打印argv[]



我试图打印给我的程序的命令行参数,使用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次,但...是垃圾

就像[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

我做了这个,这是所有你需要的

这样组装。在我的32位debian 9虚拟机上:

$ 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

最新更新