使用objdump反汇编时,如何以十六进制查看变量值?
如何获取包含字符十六进制值的汇编输出?
我编写了如下C代码,希望将其转换为汇编并查看每个字符对应的十六进制值:
#include <stdio.h> int main() { int x = 1337; char *s = "Hello world"; char buff[4] = {'a','b','c','d'}; int i = 0; while (i<4) { printf("%02x", buff[i++]); } putchar(0xa); return 0; }
但使用objdump -d test.out得到的输出不符合预期:
0000000000001149 <main>: 1149: 55 push %rbp 114a: 48 89 e5 mov %rsp,%rbp 114d: 48 83 ec 20 sub $0x20,%rsp 1151: c7 45 f8 39 05 00 00 movl $0x539,-0x8(%rbp) 1158: 48 8d 05 a5 0e 00 00 lea 0xea5(%rip),%rax # 2004 <_IO_stdin_used+0x4> 115f: 48 89 45 f0 mov %rax,-0x10(%rbp) 1163: c7 45 ec 61 62 63 64 movl $0x64636261,-0x14(%rbp) 116a: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 1171: eb 29 jmp 119c <main+0x53> 1173: 8b 45 fc mov -0x4(%rbp),%eax 1176: 8d 50 01 lea 0x1(%rax),%edx 1179: 89 55 fc mov %edx,-0x4(%rbp) 117c: 48 98 cltq 117e: 0f b6 44 05 ec movzbl -0x14(%rbp,%rax,1),%eax 1183: 0f be c0 movsbl %al,%eax 1186: 89 c6 mov %eax,%esi 1188: 48 8d 05 81 0e 00 00 lea 0xe81(%rip),%rax # 2010 <_IO_stdin_used+0x10> 118f: 48 89 c7 mov %rax,%rdi 1192: b8 00 00 00 00 mov $0x0,%eax 1197: e8 a4 fe ff ff call 1040 <printf@plt> 119c: 83 7d fc 03 cmpl $0x3,-0x4(%rbp) 11a0: 7e d1 jle 1173 <main+0x2a> 11a2: bf 0a 00 00 00 mov $0xa,%edi 11a7: e8 84 fe ff ff call 1030 <putchar@plt> 11ac: b8 00 00 00 00 mov $0x0,%eax 11b1: c9 leave 11b2: c3 ret
我期望的输出格式如下:
MOV %eax, 0x61 (for letter 'a') or something like : MOV w0, 0x61
解决方案
1. 直接生成汇编源代码
用GCC直接生成汇编文件,而非反编译二进制,能得到更贴近源码逻辑的汇编,清晰展示字符的十六进制值:
gcc -S -masm=intel test.c -o test.s
-S:仅生成汇编代码,跳过编译链接步骤-masm=intel:使用Intel格式汇编(偏好AT&T格式可省略此参数)
生成的test.s中会直接看到对应字符的十六进制定义:
.section .rodata .LC0: .string "Hello world" .LC1: .string "%02x" .text .globl main .type main, @function main: push rbp mov rbp, rsp sub rsp, 32 mov DWORD PTR [rbp-8], 1337 mov QWORD PTR [rbp-16], OFFSET FLAT:.LC0 mov DWORD PTR [rbp-20], 0x64636261 ; 对应 'd','c','b','a'(小端存储) mov DWORD PTR [rbp-4], 0 jmp .L2 .L3: mov eax, DWORD PTR [rbp-4] lea edx, [rax+1] mov DWORD PTR [rbp-4], edx cdqe movzx eax, BYTE PTR [rbp-20+rax] movsx eax, al mov esi, eax mov edi, OFFSET FLAT:.LC1 mov eax, 0 call printf .L2: cmp DWORD PTR [rbp-4], 3 jle .L3 mov edi, 10 call putchar mov eax, 0 leave ret
2. 优化objdump反编译输出
如果需要反编译可执行文件,调整参数让输出更符合预期:
objdump -d -M intel -s test.out
-M intel:切换为Intel格式汇编,和你期望的语法一致-s:显示所有段的内容,包括数据段中字符的十六进制值
输出的数据段会明确展示字符对应的十六进制:
Contents of section .rodata: 2004 48656c6c 6f20776f 726c6400 25303278 Hello world.%02x 2014 0a . Contents of section .data: ... 61626364 ... ; 对应buff数组的'a','b','c','d'
3. 快速查看字符十六进制值
若仅需确认字符的十六进制值,可通过GDB调试查看:
gdb test.out (gdb) x/4xb &buff
会直接输出buff数组每个元素的十六进制:0x61 0x62 0x63 0x64
内容的提问来源于stack exchange,提问作者bd55
相关产品推荐
相关产品推荐

