我正在尝试获取用x86汇编语言存储在argv[1]中的第一个元素。最初,我两次将堆栈弹出到eax,因为我想要argc,这样我就可以计算argc的数量。然后将argv弹出到ebx。我正在考虑将[ebx]放入bl中。从这里我迷失了。我在组装方面几乎没有经验,我只是想了解它。
main:
;
mov ecx, 0 ;count output characters
pop eax ;reject this 32 bits
pop eax ;get argc
;
pop ebx ; get argv
;mov bl, [ebx]
;
add al, 30H ;convert integer to ascii
mov edi, cline ;put char in output buffer
mov byte [edi],al
;inc edi
;mov [edi], bl
inc ecx ;increment output char count
inc edi ;increment pointer to o/p buffer
mov al, 0aH ;LF to end line
mov byte[edi],al ;put it at end of output line
inc ecx ;increment output char count
push ecx ;save char count on stack
mov edx,len ;length of string to write
mov ecx,msg ;addr of string
mov ebx,1 ;file descriptor 1 = stdout
mov eax,4 ;"write" system call
int 0x80 ;call the kernel
;
pop edx ;restore char count into edx for system call
mov ecx,cline ;address of string
mov ebx,1 ;file descriptor 1 = stdout发布于 2013-11-04 05:33:56
看看这里:NASM - Linux Getting command line parameters
下面是它的工作原理:
argc = [esp]
argv = [esp + 4 * ARG_NUMBER]其中ARG_NUMBER是指向argv的基于1的索引
./test hello there
[esp] = 3
[esp + 4 * 1] = ./test (program path and name)
[esp + 4 * 2] = hello
[esp + 4 * 3] = there我将使用C库中的printf使其更清晰:
extern printf, exit
section .data
fmtint db "%d", 10, 0
fmtstr db "%s", 10, 0
section .text
global main
main:
push dword[esp]
push fmtint
call printf ; print argc
add esp, 4 * 2
mov ebx, 1
PrintArgV:
push dword [esp + 4 * ebx]
push fmtstr
call printf ; print each param in argv
add esp, 4 * 2
inc ebx
cmp ebx, dword [esp]
jng PrintArgV
call exit为了简单起见,这里没有错误检查。您可以检查args的数量是否超出了您的预期。

@Ed Cashin,如果OP正在学习INTEL语法,为什么要将他们与AT&T混淆?
发布于 2013-11-03 09:57:51
我有三个建议:
为了获得argv,我可以简单地从我的程序中返回argv1中第一个字符的ASCII码,以避免系统调用。系统调用是一个不同于获取argv的问题,因此避免它会将注意力集中在手头的问题上。
然后,我可以编译一个最小的C程序并检查生成的程序集。阅读AT&T语法汇编并不是那么糟糕,如果您记得当您要去位于新泽西州的AT&T时,目的地在美国的右侧;;)
tmp$ cat main.c
int main(int argc, char *argv[])
{
if (argc > 1)
return argv[1][0];
return 0;
}
tmp$ gcc -Wall -save-temps main.c程序只返回argv1中第一个字符的ASCII码。“t”是116。
tmp$ ./a.out test
tmp$ echo $?
116
tmp$ 检查生成的程序集,我发现它没有使用pops,而只是基于堆栈参数相对于基指针ebp的位置来加载寄存器。我发现我喜欢这种将mov与基指针一起使用的风格。
我使用pop的方式和你想要做的不一样,所以其他人可能会评论如何使用pop。
我已经用我认为正在发生的事情给程序集添加了一点注释。欢迎更正。
tmp$ cat main.s
.file "main.c"
.text
.globl main
.type main,@function
main:
pushl %ebp ; push the callers base pointer onto the stack
movl %esp, %ebp ; save esp into the base pointer
subl $8, %esp ; make some room on the stack for main ...
andl $-16, %esp ; but pad to an aligned stack pointer
movl $0, %eax
subl %eax, %esp ; dunno why gcc subtracts 0 from stack pointer
cmpl $1, 8(%ebp) ; compare 1 and argc, which is 8 past the base pointer
jle .L2 ; jump to .L2 if argc <= 1
movl 12(%ebp), %eax ; fetch argv into eax
addl $4, %eax ; skip the first 32 bits at that address
movl (%eax), %eax ; fetch address from the resulting address
movsbl (%eax),%eax ; load byte from that address into eax
movl %eax, -4(%ebp) ; put that byte onto the stack (see note 1.)
jmp .L1
.L2:
movl $0, -4(%ebp)
.L1:
movl -4(%ebp), %eax ; load return value from stack (see note 1.)
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2.2"
tmp$ 我在32位机器上没有nasm,而且x86_64调用约定与您正在处理的不同,所以我没有将这个程序集转换成nasm语法。
https://stackoverflow.com/questions/19747803
复制相似问题