gpt4 book ai didi

linux - x86 汇编字符串缓冲区编号到 ASCII

转载 作者:太空宇宙 更新时间:2023-11-04 10:29:14 24 4
gpt4 key购买 nike

我正在编写一个 x86 汇编程序来输出一个十六进制数。该程序是使用 nasm 组装的,图像文件由 qemu 运行。该程序的行为让我很困惑。正如下面的工作程序所建议的那样,我不必将 0x30 添加到数字就可以打印该数字的字符。

    ; Boot sector code offset: 0x7c00
[org 0x7c00]

mov dx, 0x1fb6 ; The hexadecimal to be printed
call print_hex ; call the function
jmp $ ; jump infinitely

%include "print_string.asm" ; Include the print_string function

print_hex:
pusha ; push all registers to stack
mov ax, 0x4 ; rotate through the number four times
print_hex_loop:
cmp ax, 0x0 ; compare the counter with 0
jle print_hex_end ; if it is zero then jump to the end
mov cx, dx ; move dx to cx
and cx, 0x000F ; take the lower four binary digits of cx
cmp cx, 0xa ;compare the digits with 0xa
jge print_hex_letter ; if it is larger than a, jump to printing character
add cx, 0x0 ; otherwise print the ascii of a number
jmp print_hex_modify_string ; jump to routine for modifing the template
print_hex_letter:
add cx, 0x7 ; print the ascii of a letter
print_hex_modify_string:
mov bx, HEX_OUT ; bring the address of HEX_OUT into dx
add bx, 0x1 ; skip the 0x
add bx, ax ; add the bias
add byte [bx], cl ; move the character into its position
shr dx, 4 ; shift right 4 bits
sub ax, 0x1 ; subtract 1 from the counter
jmp print_hex_loop ; jump back to the start of the function
print_hex_end:
mov bx, HEX_OUT ; move the address of HEX_OUT to bx
call print_string ; call the function print_string
popa ; pop all registers from stack
ret ; return to calling function

HEX_OUT:
db '0x0000',0 ; The template string for printing

times 510-($-$$) db 0 ; fill zeros
dw 0xaa55 ; MAGIC_FLAG for boot

boot_sect.asm

print_string:
pusha
mov ah, 0x0e
mov al, [bx]
print_string_loop:
cmp al, 0x0
je print_string_end
int 0x10
add bx, 0x1
mov al, [bx]
jmp print_string_loop
print_string_end:
popa
ret

打印字符串.asm

该程序的输出符合我的预期,但是当我尝试在数字上添加 0x30 以获取数字的 ASCII 代码时,输​​出是乱码。是不是有什么技巧,还是我遗漏了一些关键点?

谢谢!

最佳答案

原始问题的答案:

因为你做add byte [bx], cl将数字写入缓冲区,而缓冲区已经包含'0',所以第一次它会正常工作.第二次调用 print_hex 将再次产生乱码,因为 HEX_OUT 内容已经被修改(琐事:第一次打印哪个十六进制数也可以正确打印第二个值? ).


现在只是为了好玩,我添加了可能如何为自己做print_hex。也许它会为您的 x86 ASM 编程提供额外的想法,我试图对其进行大量评论以解释我为什么以我正在做的方式做事:

首先我会分离格式化函数,这样我最终可以在别处重用它,所以输入既是数字又是目标缓冲区指针。我使用 LUT(查找表)进行 ASCII 转换,因为代码更简单。如果您关心大小,可以在代码中以更少的字节进行分支并使用较慢的 pusha/popa 来保存寄存器。

format_hex:
; dx = number, di = 4B output buffer for "%04X" format of number.
push bx ; used as temporary to calculate digits ASCII
push si ; used as pointer to buffer for writing chars
push dx
lea si,[di+4] ; buffer.end() pointer
format_hex_loop:
mov bx,dx ; bx = temporary to extract single digit
dec si ; si = where to write next digit
and bx,0x000F ; separate last digit (needs whole bx for LUT indexing)
shr dx,4 ; shift original number one hex-digit (4 bits) to right
mov bl,[format_hex_ascii_lut+bx] ; convert digit 0-15 value to ASCII
mov [si],bl ; write it into buffer
cmp di,si ; compare buffer.begin() with pointer-to-write
jb format_hex_loop ; loop till first digit was written
pop dx ; restore original values of all modified regs
pop si
pop bx
ret
format_hex_ascii_lut: ; LUT for 0-15 to ASCII conversion
db '0123456789ABCDEF'

然后为了方便起见,也可以添加一个 print_hex 函数,提供它自己的缓冲区以使用“0x”和 nul 终止符进行格式化:

print_hex:
; dx = number to print
push di
push bx
; format the number
mov di,HEX_OUT+2
call format_hex
; print the result to screen
lea bx,[di-2] ; bx = HEX_OUT
; HEX_OUT was already set with "0x" and nul-terminator, otherwise I would do:
; mov word [bx],'0x'
; mov byte [bx+6],0
call print_string
pop bx
pop di
ret
HEX_OUT:
db '0x1234',0 ; The template string for printing

最后是引导代码中的示例用法:

    mov     dx,0x1fb6       ; The hexadecimal to be printed
call print_hex
mov dx,ax ; works also when called second time
call print_hex ; (but would be nicer to print some space between them)

jmp $ ; loop infinitely

(我确实在一定程度上验证了这段代码(它会编译和运行),尽管只是通过它的不同部分并且在 32b 环境中(修补几行使其成为 32b),所以一些错误可能已经溜进去了。我没有 16b 环境来验证它是否是完整的引导代码。)

关于linux - x86 汇编字符串缓冲区编号到 ASCII,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40671190/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com