首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >汇编语言帮助查找agrv[1][0]

汇编语言帮助查找agrv[1][0]
EN

Stack Overflow用户
提问于 2013-11-03 06:52:57
回答 2查看 8.4K关注 0票数 1

我正在尝试获取用x86汇编语言存储在argv[1]中的第一个元素。最初,我两次将堆栈弹出到eax,因为我想要argc,这样我就可以计算argc的数量。然后将argv弹出到ebx。我正在考虑将[ebx]放入bl中。从这里我迷失了。我在组装方面几乎没有经验,我只是想了解它。

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

发布于 2013-11-04 05:33:56

看看这里:NASM - Linux Getting command line parameters

下面是它的工作原理:

代码语言:javascript
复制
argc = [esp]
argv = [esp + 4 * ARG_NUMBER]

其中ARG_NUMBER是指向argv的基于1的索引

代码语言:javascript
复制
./test hello there
[esp] = 3
[esp + 4 * 1] = ./test (program path and name)
[esp + 4 * 2] = hello
[esp + 4 * 3] = there

我将使用C库中的printf使其更清晰:

代码语言:javascript
复制
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混淆?

票数 6
EN

Stack Overflow用户

发布于 2013-11-03 09:57:51

我有三个建议:

  1. 检查http://www.nasm.us/doc/nasmdoc9.html如果您还没有,
  2. 最小化试图解决您当前问题的代码,
  3. 检查C编译器生成的程序集,如果可能,当您遇到问题时。

为了获得argv,我可以简单地从我的程序中返回argv1中第一个字符的ASCII码,以避免系统调用。系统调用是一个不同于获取argv的问题,因此避免它会将注意力集中在手头的问题上。

然后,我可以编译一个最小的C程序并检查生成的程序集。阅读AT&T语法汇编并不是那么糟糕,如果您记得当您要去位于新泽西州的AT&T时,目的地在美国的右侧;;)

代码语言:javascript
复制
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。

代码语言:javascript
复制
tmp$ ./a.out test
tmp$ echo $?
116
tmp$ 

检查生成的程序集,我发现它没有使用pops,而只是基于堆栈参数相对于基指针ebp的位置来加载寄存器。我发现我喜欢这种将mov与基指针一起使用的风格。

我使用pop的方式和你想要做的不一样,所以其他人可能会评论如何使用pop。

我已经用我认为正在发生的事情给程序集添加了一点注释。欢迎更正。

代码语言:javascript
复制
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语法。

  1. 编译器会做一些让你挠头的事情,“这是聪明的还是愚蠢的?”在这种情况下,我想我可能会使用eax本身,而不是堆栈来保存返回值,但有时googling是有教育意义的。我了解了为什么gcc有时喜欢用"xor reg,reg“将注册表归零,例如,通过谷歌搜索。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19747803

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档