Exemplo do vídeo 11 #22

Open
opened 2025-07-26 08:17:09 -03:00 by blau_araujo · 1 comment
Owner

Código utilizado no vídeo da aula 11.

Arquivo: demo.asm

section .rodata
txt1: db "abcdefghij", 0	; string com 10 caracteres + '\0'
txt2: db "ramos", 0		; string com 5 caracteres + '\0'

section .bss
buf: resb 20		; espaço para 19 caracteres + '\0'
	
section .text
global _start
_start:
	mov rdi, buf	; endereço do buffer
	mov rsi, txt1	; endereço da string
	call write_buf	; copia uma string para um buffer
	call echo_str	; imprime string no endereço em rsi

_brev:
	mov rdi, buf	; endereço do buffer
	mov rsi, txt2	; endereço da string
	call rev_buf	; inverte uma string em um buffer
	call echo_str	; imprime string no endereço em rsi

_exit:
	mov rax, 60
	xor rdi, rdi
	syscall



	
; ----------------------------------------------------------
write_buf:
; ----------------------------------------------------------
; Descrição: Copia string em rsi no buffer em rdi.
; Entradas:
;   rsi -> char *str (endereço da string)
;   rdi -> char *buf (endereço do buffer)
; Saída:
;   rsi -> char *buf (endereço do buffer)
; Altera: rax, rcx, r8, rsi (retorno)
; ----------------------------------------------------------
	mov rcx, rsi		; rcx => endereço da string
	mov r8, rdi		; r8 => endereço do buffer
.write_loop:
	mov al, byte [rcx]	; copia byte da string para rax
	cmp al, 0		; o byte em rax é 0x00?
	je .done

	mov [r8], al		; copia byte da string no buffer 
	inc rcx			; endereço do próximo byte da string
	inc r8			; endereço do próximo byte no buffer
	jmp .write_loop
.done:
	mov byte [r8], 0	; garante terminador nulo
	mov rsi, rdi		; rsi => endereço do buffer 
	ret
; ----------------------------------------------------------
rev_buf:
; ----------------------------------------------------------
; Descrição: Inverte string em rsi e salva no buffer em rdi.
; Entradas:
;   rdi -> char *buf (buffer para string invertida)	
;   rsi -> char *str (endereço da string)
; Saída:
;   rsi -> char *buf (endereço do buffer)
; Altera: rax, rcx, r8, rsi (retorno)
; Depende de str_len!
; ----------------------------------------------------------
	call str_len		; retorna tamanho da string em rax
	mov r8, rdi		; r8 => endereço do buffer
	mov rcx, rsi		; rcx => endereço da string
	add rcx, rax		; rcx => terminador da string
	dec rcx			; rcx => último caractere
.write_loop:
	mov al, byte [rcx]	; salva byte str[rcx] em rax
	mov byte [r8], al	; copia byte da origem no buffer
	dec rcx			; byte anterior na string
	inc r8			; próximo byte no buffer
	cmp rcx, rsi		; rcx < início da string?
	jb .done		; se menor, termina
	jmp .write_loop
.done:
	mov byte [r8], 0	; garante terminador nulo
	mov rsi, rdi		; rsi => endereço do buffer
	ret
; ----------------------------------------------------------
str_len:
; ----------------------------------------------------------
; Descrição: obtém o tamanho da string em rsi.
; Entrada  : rsi -> char *str (endereço da string)
; Saída    : rax -> quantidade de caracteres excluindo '\0'
; Altera   : rax (retorno), rcx
; ----------------------------------------------------------
	xor rax, rax		; zera rax para receber os bytes
	xor rcx, rcx		; contador = 0
.count_loop:
	mov al, byte [rsi+rcx]	; copia byte em rsi[rcx] para rax
	cmp al, 0		; o byte em rax é 0x00?
	je .done

	inc rcx			; contador += 1
	jmp .count_loop
.done:
	mov rax, rcx
	ret
; ----------------------------------------------------------
print_str:
; ----------------------------------------------------------
; Descrição: Imprime string em rsi.
; Entrada  : rsi -> char *src (endereço da string)
; Altera   : rax, rcx, rdx, rdi, r11	
; Depende de str_len!
; ----------------------------------------------------------
	call str_len		; retorna str_len em rax
	mov rdx, rax
	mov rax, 1
	mov rdi, 1
	syscall
	ret
; ----------------------------------------------------------
print_eol:
; ----------------------------------------------------------
; Descrição: Imprime uma quebra de linha.
; Entrada  : não tem entradas
; Altera   : rax, rcx, rdx, rdi, rsi, r11
; ----------------------------------------------------------
	push 0x0a		; salva '\n' na pilha
	mov rax, 1
	mov rdi, 1
	mov rsi, rsp
	mov rdx, 1
	syscall
	add rsp, 8		; restaura o topo da pilha
	ret
; ----------------------------------------------------------
echo_str:
; ----------------------------------------------------------
; Descrição: Imprime string em rsi com uma quebra de linha.
; Entrada  : rsi -> char *src (endereço da string)
; Saída    : Nenhuma
; Altera   : rax, rcx, rdx, rdi, rsi, r11
; Depende de str_len, print_str e print_eol!
; ----------------------------------------------------------
	call print_str
	call print_eol
	ret
; ----------------------------------------------------------

Montagem e teste:

:~$ nasm -felf64 demo.asm && ld demo.o -o demo
:~$ ./demo
abcdefghij
somar
Código utilizado no [vídeo da aula 11](https://youtu.be/6vYeFxYQ-co). Arquivo: `demo.asm` ```asm section .rodata txt1: db "abcdefghij", 0 ; string com 10 caracteres + '\0' txt2: db "ramos", 0 ; string com 5 caracteres + '\0' section .bss buf: resb 20 ; espaço para 19 caracteres + '\0' section .text global _start _start: mov rdi, buf ; endereço do buffer mov rsi, txt1 ; endereço da string call write_buf ; copia uma string para um buffer call echo_str ; imprime string no endereço em rsi _brev: mov rdi, buf ; endereço do buffer mov rsi, txt2 ; endereço da string call rev_buf ; inverte uma string em um buffer call echo_str ; imprime string no endereço em rsi _exit: mov rax, 60 xor rdi, rdi syscall ; ---------------------------------------------------------- write_buf: ; ---------------------------------------------------------- ; Descrição: Copia string em rsi no buffer em rdi. ; Entradas: ; rsi -> char *str (endereço da string) ; rdi -> char *buf (endereço do buffer) ; Saída: ; rsi -> char *buf (endereço do buffer) ; Altera: rax, rcx, r8, rsi (retorno) ; ---------------------------------------------------------- mov rcx, rsi ; rcx => endereço da string mov r8, rdi ; r8 => endereço do buffer .write_loop: mov al, byte [rcx] ; copia byte da string para rax cmp al, 0 ; o byte em rax é 0x00? je .done mov [r8], al ; copia byte da string no buffer inc rcx ; endereço do próximo byte da string inc r8 ; endereço do próximo byte no buffer jmp .write_loop .done: mov byte [r8], 0 ; garante terminador nulo mov rsi, rdi ; rsi => endereço do buffer ret ; ---------------------------------------------------------- rev_buf: ; ---------------------------------------------------------- ; Descrição: Inverte string em rsi e salva no buffer em rdi. ; Entradas: ; rdi -> char *buf (buffer para string invertida) ; rsi -> char *str (endereço da string) ; Saída: ; rsi -> char *buf (endereço do buffer) ; Altera: rax, rcx, r8, rsi (retorno) ; Depende de str_len! ; ---------------------------------------------------------- call str_len ; retorna tamanho da string em rax mov r8, rdi ; r8 => endereço do buffer mov rcx, rsi ; rcx => endereço da string add rcx, rax ; rcx => terminador da string dec rcx ; rcx => último caractere .write_loop: mov al, byte [rcx] ; salva byte str[rcx] em rax mov byte [r8], al ; copia byte da origem no buffer dec rcx ; byte anterior na string inc r8 ; próximo byte no buffer cmp rcx, rsi ; rcx < início da string? jb .done ; se menor, termina jmp .write_loop .done: mov byte [r8], 0 ; garante terminador nulo mov rsi, rdi ; rsi => endereço do buffer ret ; ---------------------------------------------------------- str_len: ; ---------------------------------------------------------- ; Descrição: obtém o tamanho da string em rsi. ; Entrada : rsi -> char *str (endereço da string) ; Saída : rax -> quantidade de caracteres excluindo '\0' ; Altera : rax (retorno), rcx ; ---------------------------------------------------------- xor rax, rax ; zera rax para receber os bytes xor rcx, rcx ; contador = 0 .count_loop: mov al, byte [rsi+rcx] ; copia byte em rsi[rcx] para rax cmp al, 0 ; o byte em rax é 0x00? je .done inc rcx ; contador += 1 jmp .count_loop .done: mov rax, rcx ret ; ---------------------------------------------------------- print_str: ; ---------------------------------------------------------- ; Descrição: Imprime string em rsi. ; Entrada : rsi -> char *src (endereço da string) ; Altera : rax, rcx, rdx, rdi, r11 ; Depende de str_len! ; ---------------------------------------------------------- call str_len ; retorna str_len em rax mov rdx, rax mov rax, 1 mov rdi, 1 syscall ret ; ---------------------------------------------------------- print_eol: ; ---------------------------------------------------------- ; Descrição: Imprime uma quebra de linha. ; Entrada : não tem entradas ; Altera : rax, rcx, rdx, rdi, rsi, r11 ; ---------------------------------------------------------- push 0x0a ; salva '\n' na pilha mov rax, 1 mov rdi, 1 mov rsi, rsp mov rdx, 1 syscall add rsp, 8 ; restaura o topo da pilha ret ; ---------------------------------------------------------- echo_str: ; ---------------------------------------------------------- ; Descrição: Imprime string em rsi com uma quebra de linha. ; Entrada : rsi -> char *src (endereço da string) ; Saída : Nenhuma ; Altera : rax, rcx, rdx, rdi, rsi, r11 ; Depende de str_len, print_str e print_eol! ; ---------------------------------------------------------- call print_str call print_eol ret ; ---------------------------------------------------------- ``` Montagem e teste: ``` :~$ nasm -felf64 demo.asm && ld demo.o -o demo :~$ ./demo abcdefghij somar ```
Author
Owner

Convenções de uso de registradores (ABI System V AMD64)

Registradores voláteis (salvos pela função chamadora):

Registrador Uso típico
rax Valor de retorno, temporário
rcx 4º argumento
rdx 3º argumento, retorno alto
rsi 2º argumento
rdi 1º argumento
r8 5º argumento
r9 6º argumento
r10 Temporário do chamador
r11 Temporário do chamador

Registradores não voláteis (preservados pela função chamada):

Registrador Uso típico
rbx Variável preservada
rbp Base da pilha (opcional)
r12 Variável preservada
r13 Variável preservada
r14 Variável preservada
r15 Variável preservada
rsp Ponteiro da pilha (sempre)
# Convenções de uso de registradores (ABI System V AMD64) Registradores voláteis (salvos pela função chamadora): | Registrador | Uso típico | |-------------|-------------------------------| | rax | Valor de retorno, temporário | | rcx | 4º argumento | | rdx | 3º argumento, retorno alto | | rsi | 2º argumento | | rdi | 1º argumento | | r8 | 5º argumento | | r9 | 6º argumento | | r10 | Temporário do chamador | | r11 | Temporário do chamador | Registradores não voláteis (preservados pela função chamada): | Registrador | Uso típico | |-------------|------------------------------| | rbx | Variável preservada | | rbp | Base da pilha (opcional) | | r12 | Variável preservada | | r13 | Variável preservada | | r14 | Variável preservada | | r15 | Variável preservada | | rsp | Ponteiro da pilha (sempre) |
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#22
No description provided.