【问题标题】:How do I print an address in x86 NASM assembly language? [duplicate]如何以 x86 NASM 汇编语言打印地址? [复制]
【发布时间】:2018-05-14 00:54:35
【问题描述】:

我正在尝试在 NASM x86 程序集中打印 变量 的地址。当我组装这段代码时,它组装得很好,但是当我运行这段代码时,它会打印两个字符而不是地址。

section .bss
Address: RESB 4

section .data
variable db 1

section .text
global _start
_start:
mov eax , variable           ; variable Address is stored in eax register
mov [Address] , dword eax    ; move the value of eax to Address
mov eax , 4                  ; write system call in linux
mov ebx , 1                  ; stdout file descriptor
mov ecx , Address            ; memory address to be printed.
mov edx , 4                  ; 4 bytes to be print
int 0x80
mov eax , 1
int 0x80

截图:

【问题讨论】:

  • write 系统调用不打印整数,而是打印字符串。您需要将地址转换为字符串,然后打印字符串
  • @MichaelPetch 明白了兄弟。如何将地址转换为字符串兄弟?我在谷歌搜索,但找不到合适的结果。
  • 检查 `iota' C 函数是如何实现的,它将整数转换为字符串。汇编程序中的提示在这里stackoverflow.com/questions/13523530/…
  • 对地址和内存内容等值使用十六进制格式也很常见,因为在十六进制格式中,每个数字正好代表 4 位。因此,一个 32 位指针将导致恰好 8 个十六进制数字 = 日志/输出中的固定宽度。加上将二进制值转换为十六进制字符串比十进制输出更简单+更快(它只是 4 位 => 1 位直接映射转换),需要认真计算。还要检查:stackoverflow.com/tags/x86/info 各种链接
  • @Naveenprakash 将地址拆分为数字,然后将每个数字转换为 ASCII。

标签: linux assembly x86 nasm system-calls


【解决方案1】:

您应该将输出格式化为十六进制数字。为此,您可以使用 C 中的 printf

extern printf

section .bss
        Address: RESB 4

section .data
        variable db 1
        fmt db "0x%x", 10, 0         ; format string

section .text
global _start
_start:
        mov eax , variable           ; variable Address is stored in eax register
        mov [Address] , dword eax    ; move the value of eax to Address

        push dword [Address]         ; push value of Address
        push dword fmt               ; address of format string
        call printf                  ; calling printf
        add esp, 8                   ; pop stack 2*4 bytes after passing two variables to printf

        mov eax, 0                   ; exit code 0
        int 0x80

【讨论】:

  • 你应该在使用像 printf 这样的 stdio 函数之后 call exit ,否则如果 stdout 是全缓冲的(例如,如果你重定向到一个文件),输出将会丢失。此外,将地址存储到单独的静态变量中,甚至先将其加载到寄存器中也没有意义。 push variable 工作得很好。
  • 一般也不建议使用_start 中的printf,尽管只要您动态地 链接它就可以在Linux 上工作。如果你静态链接,glibc init 函数永远不会被调用并且 printf 会崩溃。哦,另外,您通过调用 printf 且 ESP 未按 16 对齐,违反了 i386 System V ABI。在进入 _start 时,ESP 按 16 对齐,因此您需要额外的 sub esp, 8 才能推送 args。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多