【发布时间】:2019-03-22 05:56:00
【问题描述】:
我在 x86 程序集中发现了一个 implementation 的无符号整数转换,我尝试将其插入,但对程序集很陌生,还没有调试环境,很难理解为什么它不起作用。我还希望它可以处理有符号整数,这样它就可以从系统调用中捕获错误消息。
想知道是否可以显示如何修复此代码以打印有符号整数,而不使用 printf 而是使用 this 答案提供的 strprn。
%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax
%define EXIT 0x2000001
%define EXIT_STATUS 0
%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)
; szstr computes the lenght of a string.
; rdi - string address
; rdx - contains string length (returned)
strsz:
xor rcx, rcx ; zero rcx
not rcx ; set rcx = -1 (uses bitwise id: ~x = -x-1)
xor al,al ; zero the al register (initialize to NUL)
cld ; clear the direction flag
repnz scasb ; get the string length (dec rcx through NUL)
not rcx ; rev all bits of negative -> absolute value
dec rcx ; -1 to skip the null-term, rcx contains length
mov rdx, rcx ; size returned in rdx, ready to call write
ret
; strprn writes a string to the file descriptor.
; rdi - string address
; rdx - contains string length
strprn:
push rdi ; push string address onto stack
call strsz ; call strsz to get length
pop rsi ; pop string to rsi (source index)
mov rax, WRITE ; put write/stdout number in rax (both 1)
mov rdi, 1 ; set destination index to rax (stdout)
syscall ; call kernel
ret
; mov ebx, 0xCCCCCCCD
itoa:
xor rdi, rdi
call itoal
ret
; itoa loop
itoal:
mov ecx, eax ; save original number
mul ebx ; divide by 10 using agner fog's 'magic number'
shr edx, 3 ;
mov eax, edx ; store quotient for next loop
lea edx, [edx*4 + edx] ; multiply by 10
shl rdi, 8 ; make room for byte
lea edx, [edx*2 - '0'] ; finish *10 and convert to ascii
sub ecx, edx ; subtract from original number to get remainder
lea rdi, [rdi + rcx] ; store next byte
test eax, eax
jnz itoal
exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; exit
syscall
_main:
mov rdi, msg
call strprn
mov ebx, -0xCCCCCCCD
call itoa
call strprn
jmp exit
section .text
msg: db 0xa, " Hello StackOverflow!!!", 0xa, 0xa, 0
通过这项工作,可以将有符号整数正确打印到 STDOUT,因此您可以记录寄存器值。
- https://codereview.stackexchange.com/questions/142842/integer-to-ascii-algorithm-x86-assembly
- How to print a string to the terminal in x86-64 assembly (NASM) without syscall?
- How do I print an integer in Assembly Level Programming without printf from the c library?
- https://baptiste-wicht.com/posts/2011/11/print-strings-integers-intel-assembly.html
- How to get length of long strings in x86 assembly to print on assertion
【问题讨论】:
-
那里还没有调试环境, 先解决这个问题。我假设
lldb可用于类似于 GDB 的 asm。您需要一个可以突出显示单步执行时更改了哪些寄存器的调试器;这很有用。
标签: macos assembly x86-64 nasm itoa