如何在 NASM 中打印 argv[0]? [英] How to print argv[0] in NASM?

查看:33
本文介绍了如何在 NASM 中打印 argv[0]?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 argv[0] 存储在寄存器中然后打印它,但是当我运行我的汇编程序时出现了段错误.

I want to store argv[0] in a register and then print it, but I'm getting a segfault when I run my assembly program.

跟踪:

$ nasm -f macho -o scriptname.o --prefix _ scriptname.asm
$ ld -o scriptname scriptname.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie
$ ./scriptname
Segmentation fault: 11

脚本名称.asm:

[bits 32]

section .data

program: db "Program: %s", 0

section .text

global start
extern printf
extern exit

start:

; skip argc
add esp, 4

; ebx := argv[0]
pop ebx

push ebx
push program
call printf
add esp, 8

push 0
call exit

规格:

  • ld 64-134.9
  • nasm 0.98.40
  • Xcode 4.5
  • Mac OS X 10.8.2
  • MacBook Pro 2009

推荐答案

分段错误来自错误的堆栈对齐 (misaligned_stack_error).
当您遇到此类问题时,请始终尝试使用 GDB 运行您的程序.它通常会为您提供更多信息.

The segmentation fault comes from a bad stack alignment (misaligned_stack_error).
When you have such an issue, always try running your program with GDB. It will usually provide you with more information.

但要继续,当您从 C 库调用函数时,堆栈需要在 16 字节边界上对齐.
这是 Mac OS X 32 位 ABI 的要求(请注意,64 位 ABI 也是如此,它使用 SYS V 调用约定).

But to resume, as you are calling functions from the C library, the stack needs to be aligned on 16 bytes boundaries.
This is a requirement for the Mac OS X 32 bits ABI (note this is also the case for the 64 bits ABI, which uses the SYS V calling convention).

所以这是你的程序的一个工作版本,它将打印可执行文件的名称,以及 CLI 参数的数量(解释就在后面):

So here's a working version of your program, that will print the executable name, as well as the number of CLI arguments (explanation is just after that):

[bits 32]

section .data

    hello db "Program name: %s (%i CLI args)", 10, 0

section .text

global start
extern _exit
extern _printf

start:

    ; Store 'argc' into EAX
    pop     eax

    ; Store 'argv' into EBX
    pop     ebx

    ; Align stack on a 16 bytes boundary,
    ; as we'll use C library functions
    mov     ebp,                esp
    and     esp,                0xFFFFFFF0

    ; Stack space for local variables
    ; A little more space than needed, but that will
    ; ensure the stack is still aligned
    sub     esp,                16

    ; Call 'printf': printf( hello, ebx, eax );
    mov     dword[ esp ],       hello
    mov     dword[ esp + 4 ],   ebx
    mov     dword[ esp + 8 ],   eax
    call   _printf

    ; Call 'exit': exit( 0 );
    mov     dword[ esp ],       0
    call   _exit

编译使用:

nasm -f macho -o test.o test.asm
ld -o test test.o -arch i386 -lc -macosx_version_min 10.6

说明:

我们首先将argcargv存储在一些寄存器中:

We first store argc and argv in some registers:

    pop     eax
    pop     ebx

然后我们在 16 字节的边界上对齐堆栈:

And then we align the stack on a 16 bytes boundary:

    mov     ebp,                esp
    and     esp,                0xFFFFFFF0

假设您在为局部变量创建空间时保持堆栈对齐,您只能在 start 的开头执行此操作.

You can do this only once, at the beginning of start, assuming you keep the stack aligned, when creating space for your local variables.

然后我们为局部变量创建必要的空间,确保堆栈保持对齐.
在这里,我们只需要 3 个堆栈参数的空间,但我们为 4 个创建了空间,以保持堆栈对齐.

Then we create the necessary space for local variables, ensuring the stack is kept aligned.
Here, we only need room for 3 stack arguments, but we create space for 4, to keep the stack aligned.

    sub     esp,                16

然后您可以移动该空间上的值,为调用准备参数:

You can then move values on that space, to prepare arguments for the call:

    mov     dword[ esp ],       hello
    mov     dword[ esp + 4 ],   ebx
    mov     dword[ esp + 8 ],   eax

然后只需调用 C 库函数,就可以了.

Then simply call the C library function, and you'll be OK.

请注意,您还可以在此答案(Mac 上的 x86 程序集)中找到一些有用的信息.

Note you may also find some useful informations in this answer (x86 Assembly on a Mac).

这篇关于如何在 NASM 中打印 argv[0]?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆