x86 Assembler printf
Podemos realizar el mismo programa "Hello World" pero llamando a funciones de "C".
El llamado de funciones de "C" es diferente para arquitecturas de 32 bits y arquitecturas de 64 bits aquí nos ocuparemos de arquitecturas de 64 bits.
La convención para llamadas a rutinas de ¨C¨ desde asembler se pude ver aquí.
El siguiente programa escribe "Hello World" en pantalla usando la función de "C" printf
La convención para llamadas a rutinas de ¨C¨ desde asembler se pude ver aquí.
El siguiente programa escribe "Hello World" en pantalla usando la función de "C" printf
SECTION .data
msg: db "Hello, world,", 0
fmt: db "%s", 10, 0
SECTION .text
extern printf
global main
main:
mov esi, msg ; 64-bit Direccion comienzo de la cadena
mov edi, fmt ; Formato de la cadena
mov eax, 0 ; printf is varargs, EAX cuenta
;el numero de argumentos no enteros pasados
call printf
mov ebx, 0 ; normal-exit code
mov eax, 1 ; process-termination service
int 0x80 ; linux kernel service
Se lo asembla con:
nasm -f elf64 hello.asm -o hello.o
gcc -o hello hello.o
Se lo ejecuta:
./hello
Hello, world,
Con la función "printf" no solo podemos escribir cadenas de caracteres sino números en una variedad de formatos, en el siguiente programa podemos ver un ejemplo de impresión de números enteros de punto flotante y hexadecimales.
; printf2_64.asm use "C" printf on char, string,
; int, long int, float, double
;
; Assemble: nasm -f elf64 -l printf2.lst -o printf2.o printf2.asm
; Link: gcc -m64 -o printf2 printf2.o
; Run: ./printf2 > printf2.out
; Output: cat printf2.out
;
; A similar "C" program printf2_64.c
; #include
; int main()
; {
; char char1='a'; /* sample character */
; char str1[]="mystring"; /* sample string */
; int len=9; /* sample string */
; int inta1=12345678; /* sample integer 32-bit */
; long int inta2=12345678900; /* sample long integer 64-bit */
; long int hex1=0x123456789ABCD; /* sample hexadecimal 64-bit*/
; float flt1=5.327e-30; /* sample float 32-bit */
; double flt2=-123.4e300; /* sample double 64-bit*/
;
; printf("printf2_64: flt2=%e\n", flt2);
; printf("char1=%c, srt1=%s, len=%d\n", char1, str1, len);
; printf("char1=%c, srt1=%s, len=%d, inta1=%d, inta2=%ld\n",
; char1, str1, len, inta1, inta2);
; printf("hex1=%lX, flt1=%e, flt2=%e\n", hex1, flt1, flt2);
; return 0;
; }
extern printf ; the C function to be called
SECTION .data ; Data section
; format strings for printf
fmt2: db "printf2: flt2=%e", 10, 0
fmt3: db "char1=%c, str1=%s, len=%d", 10, 0
fmt4: db "char1=%c, str1=%s, len=%d, inta1=%d, inta2=%ld", 10, 0
fmt5: db "hex1=%lX, flt1=%e, flt2=%e", 10, 0
char1: db 'a' ; a character
str1: db "mystring",0 ; a C string, "string" needs 0
len: equ $-str1 ; len has value, not an address
inta1: dd 12345678 ; integer 12345678, note dd
inta2: dq 12345678900 ; long integer 12345678900, note dq
hex1: dq 0x123456789ABCD ; long hex constant, note dq
flt1: dd 5.327e-30 ; 32-bit floating point, note dd
flt2: dq -123.456789e300 ; 64-bit floating point, note dq
SECTION .bss
flttmp: resq 1 ; 64-bit temporary for printing flt1
SECTION .text ; Code section.
global main ; "C" main program
main: ; label, start of main program
push rbp ; set up stack frame
fld dword [flt1] ; need to convert 32-bit to 64-bit
fstp qword [flttmp] ; floating load makes 80-bit,
; store as 64-bit
mov rdi,fmt2
movq xmm0, qword [flt2]
mov rax, 1 ; 1 xmm register
call printf
mov rdi, fmt3 ; first arg, format
mov rsi, [char1] ; second arg, char
mov rdx, str1 ; third arg, string
mov rcx, len ; fourth arg, int
mov rax, 0 ; no xmm used
call printf
mov rdi, fmt4 ; first arg, format
mov rsi, [char1] ; second arg, char
mov rdx, str1 ; third arg, string
mov rcx, len ; fourth arg, int
mov r8, [inta1] ; fifth arg, inta1 32->64
mov r9, [inta2] ; sixth arg, inta2
mov rax, 0 ; no xmm used
call printf
mov rdi, fmt5 ; first arg, format
mov rsi, [hex1] ; second arg, char
movq xmm0, qword [flttmp] ; first double
movq xmm1, qword [flt2] ; second double
mov rax, 2 ; 2 xmm used
call printf
pop rbp ; restore stack
mov rax, 0 ; exit code, 0=normal
ret ; main returns to operating system
Luego lo asemblamos y linkeamos con los siguientes comandos:
nasm -f elf64 -l printf2.lst -o printf2.o printf2.asm
gcc -o printf2 printf2.o
Se lo ejecuta:
./printf2
printf2: flt2=-1.234568e+302
char1=a, str1=mystring, len=9
char1=a, str1=mystring, len=9, inta1=12345678, inta2=12345678900
hex1=123456789ABCD, flt1=5.327000e-30, flt2=-1.234568e+302
No hay comentarios:
Publicar un comentario