Exemplos da aula 4 (quarta, 9 de julho) #5

Open
opened 2025-07-09 09:50:18 -03:00 by blau_araujo · 0 comments
Owner

Programa soma

Arquivo: soma.asm

%define EOL 0x0a
%define SYS_WRITE 1
%define STDOUT 1
%define SYS_EXIT 60
%define EXIT_OK 0
%define EXIT_ERROR 1
	
section .text
global _start

_start:
	mov rdi, 42
	mov rsi, 81
	call calc_sum		; soma em rax

	mov rdi, rax		; copia soma em rdi
	call print_int64

	mov rdi, EOL		; quebra de linha
	call print_char

	mov rax, SYS_EXIT	; término do programa
	mov rdi, EXIT_OK
	syscall
	
; ----------------------------------------------------------
; int64 calc_sum(rdi + rsi)
; ----------------------------------------------------------
calc_sum:
	xor rax, rax		; zera rax para receber a soma
	mov rax, rdi		; rax = rdi
	add rax, rsi		; rax = rax + rsi
	ret

; ----------------------------------------------------------
; print_int64: imprime o valor int64 em rdi
; ----------------------------------------------------------
print_int64:
	mov rax, rdi		; copia int64 em rax
	mov rbx, 10		; divisor
	xor rcx, rcx		; zera o contador
.convert_loop:
	xor rdx, rdx		; zera o resto
	div rbx			; rax <- quociente, rdx <- resto
	add dl, 0x30		; converte o resto para ASCII
	push rdx		; salva dígito na pilha
	inc rcx			; incrementa a contagem de dígitos
	test rax, rax		; quociente (rax) == 0?
	jnz .convert_loop	; se != 0, continua
.print_loop:
	pop rdi			; último dígito convertido
	call print_char		; imprime o dígito
	dec rcx			; decrementa o contador
	jnz .print_loop
.done:
	ret

; ----------------------------------------------------------
; .print_char: imprime o byte em dil
; ----------------------------------------------------------
print_char:
	push rax		; salva rax na pilha
	push rcx		; salva rcx na pilha
	push rdi		; armazena o caractere na pilha
	
	mov rax, SYS_WRITE
	mov rdi, STDOUT		; rdi será alterado!
	mov rsi, rsp		; rsi recebe o endereço do topo da pilha
	mov rdx, 1		; só imprime o primeiro byte
	syscall

	pop rdi			; restaura rdi
	pop rcx			; restaura rcx
	pop rax			; restaura rax
	ret

Montar e ligar com:

:~$ nasm -felf64 soma.asm
:~$ ld soma.o -o soma

Modelo para ELF64 mínimo

Arquivo: elf-header.asm

%define LOAD_ADDR 0x400000
%define VADDR LOAD_ADDR+0x78 	; endereço virtual do segmento na memória
%define CODE_SIZE END-VADDR     ; tamanho do conteúdo executável
	
bits 64
org LOAD_ADDR

; ------------------------------------------------------------------------------
; Cabeçalhos ELF64
; ------------------------------------------------------------------------------
ELF_HEADER:
	db 0x7F, "ELF"	; bytes 0-3   : número mágico
	db 0x02		; byte 4      : 1 = 32-bit, 2 = 64-bit
	db 0x01		; byte 5      : 1 = LE, 2 = BE
	db 0x01	        ; byte 6      : 1 = versão corrente do cabeçalho ELF
	db 0x00	        ; byte 7      : 0 = UNIX System V ABI
	dq 0x00	        ; bytes 8-15  : padding
	dw 0x02	        ; bytes 16-17 : 1 = rel, 2 = exec, 3 = shared, 4 = core
	dw 0x3e         ; bytes 18-19 : 0x3e = x86-64
	dd 0x01	        ; bytes 20-23 : versão corrente do ELF (1)
	dq START	; bytes 24-31 : ponto de entrada do programa
	dq 0x40		; bytes 32-39 : início do cabeçalho do programa
	dq 0x00		; bytes 40-47 : início do cabeçalho de seções (não vamos usar)
	dd 0x00		; bytes 48-51 : flags (não utilizadas no x86)
	dw 0x40		; bytes 52-53 : tamanho do cabeçalho ELF (64 bytes = 0x40)
	dw 0x38		; bytes 54-55 : tamanho do cab. do prog. (56 bytes = 0x38)
	dw 0x01		; bytes 56-57 : entradas no cab. do prog. (só teremos uma)
	dw 0x00		; bytes 58-59 : tamanho do cab. de seções (não vamos usar)
	dw 0x00		; bytes 60-61 : entradas no cab. de seções (não vamos usar)
	dw 0x00		; bytes 62-63 : índice das strings dos cab. de seções (não temos)

PROG_HEADER:
	dd 0x01		; bytes 0-3   : tipo de segmento (1 = segmento carregável)
	dd 0x05		; bytes 4-7   : permissões r-x (r=4, w=2, x=1)
	dq 0x78		; bytes 8-15  : offset do início do código (120 bytes = 0x78)
	dq VADDR	; bytes 16-23 : endereço virtual do segmento na memória
	dq 0x00		; bytes 24-31 : reservado para endereço físico do segmento
	dq CODE_SIZE	; bytes 32-39 : tamanho do segmento no arquivo
	dq CODE_SIZE	; bytes 40-47 : tamanho do segmento na memória
	dq 0x10		; bytes 48-55 : alinhamento (16 bytes, mas não importa)
; ------------------------------------------------------------------------------
; Código do programa
; ------------------------------------------------------------------------------
START:

; %include "ARQUIVO DO PROGRAMA"

END:

Programa soma-min

Arquivo: soma-min.asm

Este arquivo é igual ao soma.asm, mas sem a definição da seção .text e do ponto de entrada global.

%define EOL 0x0a
%define SYS_WRITE 1
%define STDOUT 1
%define SYS_EXIT 60
%define EXIT_OK 0
%define EXIT_ERROR 1
	
	mov rdi, 42
	mov rsi, 81
	call calc_sum		; soma em rax

	mov rdi, rax		; copia soma em rdi
	call print_int64

	mov rdi, EOL		; quebra de linha
	call print_char

	mov rax, SYS_EXIT	; término do programa
	mov rdi, EXIT_OK
	syscall
	
; ----------------------------------------------------------
; int64 calc_sum(rdi + rsi)
; ----------------------------------------------------------
calc_sum:
	xor rax, rax		; zera rax para receber a soma
	mov rax, rdi		; rax = rdi
	add rax, rsi		; rax = rax + rsi
	ret

; ----------------------------------------------------------
; print_int64: imprime o valor int64 em rdi
; ----------------------------------------------------------
print_int64:
	mov rax, rdi		; copia int64 em rax
	mov rbx, 10		; divisor
	xor rcx, rcx		; zera o contador
.convert_loop:
	xor rdx, rdx		; zera o resto
	div rbx			; rax <- quociente, rdx <- resto
	add dl, 0x30		; converte o resto para ASCII
	push rdx		; salva dígito na pilha
	inc rcx			; incrementa a contagem de dígitos
	test rax, rax		; quociente (rax) == 0?
	jnz .convert_loop	; se != 0, continua
.print_loop:
	pop rdi			; último dígito convertido
	call print_char		; imprime o dígito
	dec rcx			; decrementa o contador
	jnz .print_loop
.done:
	ret

; ----------------------------------------------------------
; .print_char: imprime o byte em dil
; ----------------------------------------------------------
print_char:
	push rax		; salva rax na pilha
	push rcx		; salva rcx na pilha
	push rdi		; armazena o caractere na pilha
	
	mov rax, SYS_WRITE
	mov rdi, STDOUT		; rdi será alterado!
	mov rsi, rsp		; rsi recebe o endereço do topo da pilha
	mov rdx, 1		; só imprime o primeiro byte
	syscall

	pop rdi			; restaura rdi
	pop rcx			; restaura rcx
	pop rax			; restaura rax
	ret

Incluir no modelo ELF64:

%include "soma-min.asm"

Montar como binário bruto:

:~$ nasm -f bin elf-header.asm -o soma-min

Dar permissão de execução e testar:

:~$ chmod +x soma-min
:~$ ./soma-min
123
## Programa soma Arquivo: `soma.asm` ```asm %define EOL 0x0a %define SYS_WRITE 1 %define STDOUT 1 %define SYS_EXIT 60 %define EXIT_OK 0 %define EXIT_ERROR 1 section .text global _start _start: mov rdi, 42 mov rsi, 81 call calc_sum ; soma em rax mov rdi, rax ; copia soma em rdi call print_int64 mov rdi, EOL ; quebra de linha call print_char mov rax, SYS_EXIT ; término do programa mov rdi, EXIT_OK syscall ; ---------------------------------------------------------- ; int64 calc_sum(rdi + rsi) ; ---------------------------------------------------------- calc_sum: xor rax, rax ; zera rax para receber a soma mov rax, rdi ; rax = rdi add rax, rsi ; rax = rax + rsi ret ; ---------------------------------------------------------- ; print_int64: imprime o valor int64 em rdi ; ---------------------------------------------------------- print_int64: mov rax, rdi ; copia int64 em rax mov rbx, 10 ; divisor xor rcx, rcx ; zera o contador .convert_loop: xor rdx, rdx ; zera o resto div rbx ; rax <- quociente, rdx <- resto add dl, 0x30 ; converte o resto para ASCII push rdx ; salva dígito na pilha inc rcx ; incrementa a contagem de dígitos test rax, rax ; quociente (rax) == 0? jnz .convert_loop ; se != 0, continua .print_loop: pop rdi ; último dígito convertido call print_char ; imprime o dígito dec rcx ; decrementa o contador jnz .print_loop .done: ret ; ---------------------------------------------------------- ; .print_char: imprime o byte em dil ; ---------------------------------------------------------- print_char: push rax ; salva rax na pilha push rcx ; salva rcx na pilha push rdi ; armazena o caractere na pilha mov rax, SYS_WRITE mov rdi, STDOUT ; rdi será alterado! mov rsi, rsp ; rsi recebe o endereço do topo da pilha mov rdx, 1 ; só imprime o primeiro byte syscall pop rdi ; restaura rdi pop rcx ; restaura rcx pop rax ; restaura rax ret ``` Montar e ligar com: ``` :~$ nasm -felf64 soma.asm :~$ ld soma.o -o soma ``` ## Modelo para ELF64 mínimo Arquivo: `elf-header.asm` ```asm %define LOAD_ADDR 0x400000 %define VADDR LOAD_ADDR+0x78 ; endereço virtual do segmento na memória %define CODE_SIZE END-VADDR ; tamanho do conteúdo executável bits 64 org LOAD_ADDR ; ------------------------------------------------------------------------------ ; Cabeçalhos ELF64 ; ------------------------------------------------------------------------------ ELF_HEADER: db 0x7F, "ELF" ; bytes 0-3 : número mágico db 0x02 ; byte 4 : 1 = 32-bit, 2 = 64-bit db 0x01 ; byte 5 : 1 = LE, 2 = BE db 0x01 ; byte 6 : 1 = versão corrente do cabeçalho ELF db 0x00 ; byte 7 : 0 = UNIX System V ABI dq 0x00 ; bytes 8-15 : padding dw 0x02 ; bytes 16-17 : 1 = rel, 2 = exec, 3 = shared, 4 = core dw 0x3e ; bytes 18-19 : 0x3e = x86-64 dd 0x01 ; bytes 20-23 : versão corrente do ELF (1) dq START ; bytes 24-31 : ponto de entrada do programa dq 0x40 ; bytes 32-39 : início do cabeçalho do programa dq 0x00 ; bytes 40-47 : início do cabeçalho de seções (não vamos usar) dd 0x00 ; bytes 48-51 : flags (não utilizadas no x86) dw 0x40 ; bytes 52-53 : tamanho do cabeçalho ELF (64 bytes = 0x40) dw 0x38 ; bytes 54-55 : tamanho do cab. do prog. (56 bytes = 0x38) dw 0x01 ; bytes 56-57 : entradas no cab. do prog. (só teremos uma) dw 0x00 ; bytes 58-59 : tamanho do cab. de seções (não vamos usar) dw 0x00 ; bytes 60-61 : entradas no cab. de seções (não vamos usar) dw 0x00 ; bytes 62-63 : índice das strings dos cab. de seções (não temos) PROG_HEADER: dd 0x01 ; bytes 0-3 : tipo de segmento (1 = segmento carregável) dd 0x05 ; bytes 4-7 : permissões r-x (r=4, w=2, x=1) dq 0x78 ; bytes 8-15 : offset do início do código (120 bytes = 0x78) dq VADDR ; bytes 16-23 : endereço virtual do segmento na memória dq 0x00 ; bytes 24-31 : reservado para endereço físico do segmento dq CODE_SIZE ; bytes 32-39 : tamanho do segmento no arquivo dq CODE_SIZE ; bytes 40-47 : tamanho do segmento na memória dq 0x10 ; bytes 48-55 : alinhamento (16 bytes, mas não importa) ; ------------------------------------------------------------------------------ ; Código do programa ; ------------------------------------------------------------------------------ START: ; %include "ARQUIVO DO PROGRAMA" END: ``` ## Programa soma-min Arquivo: `soma-min.asm` Este arquivo é igual ao `soma.asm`, mas sem a definição da seção `.text` e do ponto de entrada global. ```asm %define EOL 0x0a %define SYS_WRITE 1 %define STDOUT 1 %define SYS_EXIT 60 %define EXIT_OK 0 %define EXIT_ERROR 1 mov rdi, 42 mov rsi, 81 call calc_sum ; soma em rax mov rdi, rax ; copia soma em rdi call print_int64 mov rdi, EOL ; quebra de linha call print_char mov rax, SYS_EXIT ; término do programa mov rdi, EXIT_OK syscall ; ---------------------------------------------------------- ; int64 calc_sum(rdi + rsi) ; ---------------------------------------------------------- calc_sum: xor rax, rax ; zera rax para receber a soma mov rax, rdi ; rax = rdi add rax, rsi ; rax = rax + rsi ret ; ---------------------------------------------------------- ; print_int64: imprime o valor int64 em rdi ; ---------------------------------------------------------- print_int64: mov rax, rdi ; copia int64 em rax mov rbx, 10 ; divisor xor rcx, rcx ; zera o contador .convert_loop: xor rdx, rdx ; zera o resto div rbx ; rax <- quociente, rdx <- resto add dl, 0x30 ; converte o resto para ASCII push rdx ; salva dígito na pilha inc rcx ; incrementa a contagem de dígitos test rax, rax ; quociente (rax) == 0? jnz .convert_loop ; se != 0, continua .print_loop: pop rdi ; último dígito convertido call print_char ; imprime o dígito dec rcx ; decrementa o contador jnz .print_loop .done: ret ; ---------------------------------------------------------- ; .print_char: imprime o byte em dil ; ---------------------------------------------------------- print_char: push rax ; salva rax na pilha push rcx ; salva rcx na pilha push rdi ; armazena o caractere na pilha mov rax, SYS_WRITE mov rdi, STDOUT ; rdi será alterado! mov rsi, rsp ; rsi recebe o endereço do topo da pilha mov rdx, 1 ; só imprime o primeiro byte syscall pop rdi ; restaura rdi pop rcx ; restaura rcx pop rax ; restaura rax ret ``` Incluir no modelo ELF64: ```asm %include "soma-min.asm" ``` Montar como binário bruto: ``` :~$ nasm -f bin elf-header.asm -o soma-min ``` Dar permissão de execução e testar: ``` :~$ chmod +x soma-min :~$ ./soma-min 123 ```
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: blau_araujo/pbn#5
No description provided.