Bla*_*ear 13
你必须用字符串转换它; 如果你在谈论十六进制数字,这很容易.任何数字都可以这样表示:
0xa31f = 0xf * 16^0 + 0x1 * 16^1 + 3 * 16^2 + 0xa * 16^3
Run Code Online (Sandbox Code Playgroud)
因此,当你有这个数字时,你必须像我展示的那样拆分它,然后将每个"部分"转换为它的ASCII等价物.
获得这四个部分很容易完成一些魔术,特别是右移以在前四位移动我们感兴趣的部分,然后用0xf将结果与其余部分隔离.这就是我的意思(我们希望采用3):
0xa31f -> shift right by 8 = 0x00a3 -> AND with 0xf = 0x0003
Run Code Online (Sandbox Code Playgroud)
现在我们只有一个数字,我们必须将其转换为ASCII值.如果数字小于或等于9,我们可以添加0的ASCII值(0x30),如果它大于9,我们必须使用ASCII值(0x61).
在这里,现在我们只需编写代码:
mov si, ??? ; si points to the target buffer
mov ax, 0a31fh ; ax contains the number we want to convert
mov bx, ax ; store a copy in bx
xor dx, dx ; dx will contain the result
mov cx, 3 ; cx's our counter
convert_loop:
mov ax, bx ; load the number into ax
and ax, 0fh ; we want the first 4 bits
cmp ax, 9h ; check what we should add
ja greater_than_9
add ax, 30h ; 0x30 ('0')
jmp converted
greater_than_9:
add ax, 61h ; or 0x61 ('a')
converted:
xchg al, ah ; put a null terminator after it
mov [si], ax ; (will be overwritten unless this
inc si ; is the last one)
shr bx, 4 ; get the next part
dec cx ; one less to do
jnz convert_loop
sub di, 4 ; di still points to the target buffer
Run Code Online (Sandbox Code Playgroud)
PS:我知道这是16位代码,但我仍然使用旧的TASM:P
PPS:这是英特尔语法,虽然转换为AT&T语法并不困难,但请看这里.
Mar*_*tin 13
如果您已经在Linux上,则无需自行进行转换.只需使用printf代替:
;
; assemble and link with:
; nasm -f elf printf-test.asm && gcc -m32 -o printf-test printf-test.o
;
section .text
global main
extern printf
main:
mov eax, 0xDEADBEEF
push eax
push message
call printf
add esp, 8
ret
message db "Register = %08X", 10, 0
Run Code Online (Sandbox Code Playgroud)
请注意,printf使用cdecl调用约定,因此我们需要在之后恢复堆栈指针,即每个传递给函数的参数添加4个字节.
带有 printf 的 Linux x86-64
主程序
default rel ; make [rel format] the default, you always want this.
extern printf, exit ; NASM requires declarations of external symbols, unlike GAS
section .rodata
format db "%#x", 10, 0 ; C 0-terminated string: "%#x\n"
section .text
global main
main:
sub rsp, 8 ; re-align the stack to 16 before calling another function
; Call printf.
mov esi, 0x12345678 ; "%x" takes a 32-bit unsigned int
lea rdi, [rel format]
xor eax, eax ; AL=0 no FP args in XMM regs
call printf
; Return from main.
xor eax, eax
add rsp, 8
ret
Run Code Online (Sandbox Code Playgroud)
然后:
nasm -f elf64 -o main.o main.asm
gcc -no-pie -o main.out main.o
./main.out
Run Code Online (Sandbox Code Playgroud)
输出:
0x12345678
Run Code Online (Sandbox Code Playgroud)
笔记:
sub rsp, 8:如何使用 printf 为 64 位 Mac OS X 编写汇编语言 hello world 程序?xor eax, eax:为什么 %eax 在调用 printf 之前归零?-no-pie:plaincall printf在 PIE 可执行文件 ( -pie) 中不起作用,链接器只会为旧式可执行文件自动生成 PLT 存根。您的选择是:
call printf wrt ..plt 像传统一样通过 PLT 调用 call printf
call [rel printf wrt ..got]根本不使用 PLT,例如gcc -fno-plt.
像 GAS 语法call *printf@GOTPCREL(%rip)。
在非 PIE 可执行文件中,这些都很好,除非您静态链接 libc,否则不会导致任何低效率。在这种情况下,call printf可以call rel32直接解析为libc,因为从您的代码到 libc 函数的偏移量在静态链接时是已知的。
如果你想要没有 C 库的十六进制:用汇编打印十六进制数字
在 Ubuntu 18.10、NASM 2.13.03 上测试。
| 归档时间: |
|
| 查看次数: |
29599 次 |
| 最近记录: |