Posterior a de una larga compilación de datos pudimos solucionar este disgusto que pueden tener muchos de nuestros usuarios. Te brindamos la respuesta y nuestro deseo es servirte de mucha ayuda.
Solución:
Si ya está en Linux, no es necesario que haga la conversión usted mismo. Simplemente use printf en su lugar:
;
; 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
Tenga en cuenta que printf
usa la convención de llamada cdecl, por lo que necesitamos restaurar el puntero de la pila después, es decir, agregar 4 bytes por parámetro pasado a la función.
Tienes que convertirlo en un string; si estás hablando de números hexadecimales, es bastante fácil. Cualquier número se puede representar de esta manera:
0xa31f = 0xf * 16^0 + 0x1 * 16^1 + 3 * 16^2 + 0xa * 16^3
Entonces, cuando tenga este número, debe dividirlo como se muestra y luego convertir cada “sección” a su equivalente ASCII.
Obtener las cuatro partes se hace fácilmente con un poco de magia, en particular con un desplazamiento a la derecha para mover la parte que nos interesa en los primeros cuatro bits y luego Y el resultado con 0xf para aislarlo del resto. Esto es lo que quiero decir (supongamos que queremos tomar el 3):
0xa31f -> shift right by 8 = 0x00a3 -> AND with 0xf = 0x0003
Ahora que tenemos un solo número, tenemos que convertirlo a su valor ASCII. Si el número es menor o igual a 9, simplemente podemos agregar el valor ASCII de 0 (0x30), si es mayor que 9, debemos usar el valor ASCII de a (0x61).
Aquí está, ahora solo tenemos que codificarlo:
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
PD: Sé que este es un código de 16 bits, pero sigo usando el antiguo TASM: P
ppd: esta es la sintaxis de Intel, sin embargo, la conversión a la sintaxis de AT&T no es difícil, mire aquí.
Linux x86-64 con impresión
principal.asm
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: "%#xn"
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
GitHub en sentido ascendente.
Entonces:
nasm -f elf64 -o main.o main.asm
gcc -no-pie -o main.out main.o
./main.out
Producción:
0x12345678
Notas:
sub rsp, 8
: ¿Cómo escribir el programa hello world en lenguaje ensamblador para Mac OS X de 64 bits usando printf?xor eax, eax
: ¿Por qué %eax se pone a cero antes de una llamada a printf?-
-no-pie
: planocall printf
no funciona en un ejecutable PIE (-pie
), el enlazador solo genera automáticamente un código auxiliar PLT para ejecutables de estilo antiguo. Tus opciones son:-
call printf wrt ..plt
llamar a través del PLT como tradicionalcall printf
-
call [rel printf wrt ..got]
no usar un PLT en absoluto, comogcc -fno-plt
.
Como la sintaxis de GAS
call *[email protected](%rip)
.Cualquiera de estos también está bien en un ejecutable que no sea PIE, y no causa ninguna ineficiencia a menos que esté vinculando estáticamente libc. En ese caso
call printf
puede resolver uncall rel32
directamente a libc, porque el desplazamiento de su código a la función libc se conocería en static tiempo de enlace.Ver también: No se puede llamar a la función de biblioteca estándar de C en Linux de 64 bits desde el código ensamblador (yasm)
-
Si desea hexadecimal sin la biblioteca C: Impresión de dígitos hexadecimales con ensamblaje
Probado en Ubuntu 18.10, NASM 2.13.03.
Tienes la posibilidad recomendar este enunciado si te fue útil.