【问题标题】:Print 2nd command line argument打印第二个命令行参数
【发布时间】:2016-03-20 20:12:15
【问题描述】:

我正在编写一个打印程序第二个参数的代码。我知道ebp+8 保存参数的数量,ebp+12 保存程序名称的地址等等。到目前为止,我有:

%include "asm_io.inc"

SECTION .data
err1: db "Incorrect number of command line arguments",10,0

SECTION .text 
    global  asm_main

asm_main:
   enter 0,0
   pusha

   mov eax, dword [ebp+8]
   cmp eax, dword 2
   jne ERR1

   mov eax, dword [ebp+16]  ; prints 1st letter of 2nd argument
   mov al, byte[eax]
   call print_string
   jmp asm_main_end


 ERR1:
   mov eax, err1
   call print_string
   jmp asm_main_end

 asm_main_end:
   call print_nl
   popa                  ; restore all registers
   leave                     
   ret

可执行文件名为lynarr。当我执行lynarr abcd 时,我能够打印程序名称(即lynarr),但我不明白如何打印第二个参数。我正在使用 redhat-linux 和 nasm 2.10.07。有任何想法吗?

【问题讨论】:

    标签: linux assembly x86 command-line-arguments nasm


    【解决方案1】:

    dword [ebp+12] 是一个指向字符串指针数组的指针。该数组的第一个元素是指向第一个字符串的指针,第二个元素是指向第二个字符串的指针,依此类推。每个指针都是 32 位(4 字节)宽。

    要获得指向第二个字符串的指针,需要获得位于dword [ebp+12] + 4 的指针。您不能直接在 x86 寻址中执行此操作。您可以通过将dword [ebp+12] 移动到像 EAX 这样的寄存器中来做到这一点,向它添加 4(因为指针是 4 字节宽),然后取消引用它以获得第二个字符串的指针。

    替换:

    mov eax, dword [ebp+16]  ; prints 1st letter of 2nd argument
    mov al, byte[eax]
    call print_string
    

    与:

    mov eax, dword [ebp+12]  
    mov eax, [eax+4]          ; EAX = pointer to 2nd argument
    call print_string
    

    这将打印出第二个参数。第一个参数可以打印出来:

    mov eax, dword [ebp+12]  
    mov eax, [eax]           ; EAX = pointer to 1st argument
    call print_string
    

    当然mov eax, [eax+8] 会得到第三个参数,依此类推。

    您不能使用print_string 打印寄存器中的单个字符(如AL)。 EAX 必须是指向 NUL(\0) 终止字符串的指针。


    您可以做的其他事情是使用scaled index addressing 单步执行数组(如您的参数):

    mov ebx, dword [ebp+12]  
    xor esi, esi            ; Index of first argument (index=0) 
    mov eax, [ebx+esi*4]    ; EAX = pointer to 1st argument
    call print_string
    inc esi                 ; Next argument (index=1)
    mov eax, [ebx+esi*4]    ; EAX = pointer to 2nd argument
    call print_string
    inc esi                 ; Next argument (index=2)
    mov eax, [ebx+esi*4]    ; EAX = pointer to 3rd argument
    call print_string
    

    有了这个想法,您可能会看到如何创建一个遍历参数的循环。我把它留给读者作为练习。这是另一个方便的quick reference 寻址模式。

    【讨论】:

    • 谢谢!我试图直接跳到ebp+16,我现在可以看到这是错误的。另外,我不知道 print_string 不能用于打印 AL。非常感谢!
    • 是的,我看到了。您只需要先取消引用 [ebp+12] 然后添加 4。您几乎知道必须添加 4 才能到达下一个元素。您只需要有正确的指针即可。
    • @Sally 我添加了一个关于使用缩放索引寻址的部分,稍后您可能会发现它很有用。
    • 我还没有使用太多esiedi,但我绝对可以看到实用程序!我会确保我阅读了。
    • @Sally 这很可能是您最终会接触到的东西(尤其是在您参加课程时),并且对于处理数组非常有用。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 2015-06-03
    • 2021-03-12
    • 2020-05-05
    • 2016-05-01
    • 2018-06-28
    • 2023-04-03
    相关资源
    最近更新 更多