打印第二个命令行参数
Print 2nd command line argument
我正在编写打印出程序第二个参数的代码。我知道 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。有任何想法吗?
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]
会得到第3个参数等等。
您不能使用 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
有了这个想法,您可能会看到如何创建一个遍历参数的循环。我将其留作 reader 的练习。这是另一种方便的 quick reference 寻址模式。
我正在编写打印出程序第二个参数的代码。我知道 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。有任何想法吗?
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]
会得到第3个参数等等。
您不能使用 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
有了这个想法,您可能会看到如何创建一个遍历参数的循环。我将其留作 reader 的练习。这是另一种方便的 quick reference 寻址模式。