Exemplos do vídeo 15 #33

Open
opened 2025-08-20 10:02:55 -03:00 by blau_araujo · 0 comments
Owner

Arquivo: mycat.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

long print_file(const char *filename, void *buf, unsigned long size);

int main (int argc, char **argv) {

    /* Verificação dos argumentos... */
    if (argc < 2) {
        fprintf(stderr, "Uso: %s <arquivo>\n", argv[0]);
        return EXIT_FAILURE;
    }

    /* Impressão do arquivo... */
    char buffer[BUFSIZ];
    long filesize = print_file(argv[1], buffer, BUFSIZ);

    /* Erro na abertura do arquivo... */
    if (filesize < 0) {
        errno = -filesize;
        perror(argv[1]);
        return EXIT_FAILURE;
    }

    /* Impressão do tamanho do arquivo... */
    printf("---\n%s: %ld bytes\n", argv[1], filesize);
                            
    return EXIT_SUCCESS;
}

Arquivo: printfile.asm

%define SYS_READ    0
%define SYS_WRITE   1
%define SYS_OPEN    2
%define SYS_CLOSE   3
%define SYS_EXIT    60
;----------------------------------------------------
%define STDOUT      1
%define STDERR      2
;----------------------------------------------------
%define EXIT_OK     0
%define EXIT_ERROR  1
;----------------------------------------------------
%define O_RDONLY    0
;----------------------------------------------------
	
global print_file

; ----------------------------------------------------------
print_file:
; ----------------------------------------------------------
; Lê e imprime conteúdo do arquivo
; ----------------------------------------------------------
; rdi <- nome do arquivo (char *filename)
; rsi <- endereço do buffer (void *buf)
; rdx <- tamanho do buffer (unsigned long size)
; ----------------------------------------------------------
; rax -> quantidade de bytes impressos ou -errno, em caso de erro
; ----------------------------------------------------------
; Altera: rax, rcx, rdx, rdi, rsi, r8, r11
; ----------------------------------------------------------
	push rdx		; salva tamanho do buffer
	push rsi		; salva endereço do buffer
.get_fd:
	call open_file		; abre arquivo apenas para leitura
	cmp rax, 0		; se negativo, erro de abertura do arquivo
	jl .error		; rax (retorno) será -errno
.print_lines:
	mov rdi, rax		; rdi -> descritor de arquivo
	pop rsi			; restaura endereço do buffer
	pop rdx			; restaura tamanho do buffer
	call read_loop		; imprime as linhas do arquivo
	push rax		; salva quantidade de bytes impressos (ou erro)
.close_fd:
	call close_file		; fecha o descritor de arquivo
.success:
	pop rax			; rax (retorno) -> bytes impressos (ou erro)
	ret
.error:
	pop rsi
	pop rdx
	ret

;----------------------------------------------------
read_loop:
;----------------------------------------------------
; Lê e imprime as linhas do arquivo
;----------------------------------------------------
; rdi <- descritor de arquivos
; rsi <- endereço do buffer
; rdx <- tamanho do buffer
;----------------------------------------------------
; rax -> quantidade de bytes impressos ou -errno, em caso de erro
;----------------------------------------------------
; Altera: rax, rcx, rdx, rdi, r8, r11
;----------------------------------------------------
	xor r8, r8		; zera r8 para contagem de bytes lidos
.loop:
	; Lendo o arquivo
	mov rax, SYS_READ       ; syscall read
	syscall
	cmp rax, 0
	jl .done		; se -errno, termina com erro
	je .return		; se 0, retorna qtd. de bytes lidos
.print_line:
	add r8, rax		; r8+=rax
	push rdi                ; salva rdi (fd) na pilha
	push rdx		; salva rdx (buf size) na pilha
	
	mov rdx, rax            ; imprimir até qtd. de bytes lidos
	mov rax, SYS_WRITE      ; syscall write
	mov rdi, STDOUT         ; saída padrão
	syscall

	pop rdx			; restaura buffer size
	pop rdi                 ; restaura fd

	jmp .loop
.return:
	mov rax, r8
.done:
	ret

;----------------------------------------------------
close_file:
;----------------------------------------------------
; Fecha o arquivo associado a fd
;----------------------------------------------------
; rdi <- descritor de arquivos
;----------------------------------------------------
; Altera: rax, rcx, r11
;----------------------------------------------------
	mov rax, SYS_CLOSE      ; syscall close
	syscall
	ret

;----------------------------------------------------
open_file:
;----------------------------------------------------
; Abre o arquivo apenas para leitura
;----------------------------------------------------
; rdi <- caminho do arquivo
; rax -> descritor de arquivo ou erro (-1)
;----------------------------------------------------
; Altera: rax, rcx, r11 
;----------------------------------------------------
	mov rax, SYS_OPEN       ; syscall open
	mov rsi, O_RDONLY       ; flag somente leitura
	mov rdx, 0              ; usado apenas quando um novo arquivo é criado
	syscall
	ret
;----------------------------------------------------
; section .note.GNU-stack noalloc noexec nowrite
;----------------------------------------------------

Montagem e compilação:

:~$ nasm -felf64 printfile.asm
:~$ gcc -Wall -Wextra printfile.o mycat.c -o mycat

Teste:

:~$ ./mycat xxx
xxx: No such file or directory
:~$ ./mycat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/usr/bin/dash
/usr/bin/sh
/usr/bin/tmux
/bin/zsh
/usr/bin/zsh
---
/etc/shells: 154 bytes
**Arquivo:** `mycat.c` ```c #include <stdio.h> #include <stdlib.h> #include <errno.h> long print_file(const char *filename, void *buf, unsigned long size); int main (int argc, char **argv) { /* Verificação dos argumentos... */ if (argc < 2) { fprintf(stderr, "Uso: %s <arquivo>\n", argv[0]); return EXIT_FAILURE; } /* Impressão do arquivo... */ char buffer[BUFSIZ]; long filesize = print_file(argv[1], buffer, BUFSIZ); /* Erro na abertura do arquivo... */ if (filesize < 0) { errno = -filesize; perror(argv[1]); return EXIT_FAILURE; } /* Impressão do tamanho do arquivo... */ printf("---\n%s: %ld bytes\n", argv[1], filesize); return EXIT_SUCCESS; } ``` **Arquivo:** `printfile.asm` ```asm %define SYS_READ 0 %define SYS_WRITE 1 %define SYS_OPEN 2 %define SYS_CLOSE 3 %define SYS_EXIT 60 ;---------------------------------------------------- %define STDOUT 1 %define STDERR 2 ;---------------------------------------------------- %define EXIT_OK 0 %define EXIT_ERROR 1 ;---------------------------------------------------- %define O_RDONLY 0 ;---------------------------------------------------- global print_file ; ---------------------------------------------------------- print_file: ; ---------------------------------------------------------- ; Lê e imprime conteúdo do arquivo ; ---------------------------------------------------------- ; rdi <- nome do arquivo (char *filename) ; rsi <- endereço do buffer (void *buf) ; rdx <- tamanho do buffer (unsigned long size) ; ---------------------------------------------------------- ; rax -> quantidade de bytes impressos ou -errno, em caso de erro ; ---------------------------------------------------------- ; Altera: rax, rcx, rdx, rdi, rsi, r8, r11 ; ---------------------------------------------------------- push rdx ; salva tamanho do buffer push rsi ; salva endereço do buffer .get_fd: call open_file ; abre arquivo apenas para leitura cmp rax, 0 ; se negativo, erro de abertura do arquivo jl .error ; rax (retorno) será -errno .print_lines: mov rdi, rax ; rdi -> descritor de arquivo pop rsi ; restaura endereço do buffer pop rdx ; restaura tamanho do buffer call read_loop ; imprime as linhas do arquivo push rax ; salva quantidade de bytes impressos (ou erro) .close_fd: call close_file ; fecha o descritor de arquivo .success: pop rax ; rax (retorno) -> bytes impressos (ou erro) ret .error: pop rsi pop rdx ret ;---------------------------------------------------- read_loop: ;---------------------------------------------------- ; Lê e imprime as linhas do arquivo ;---------------------------------------------------- ; rdi <- descritor de arquivos ; rsi <- endereço do buffer ; rdx <- tamanho do buffer ;---------------------------------------------------- ; rax -> quantidade de bytes impressos ou -errno, em caso de erro ;---------------------------------------------------- ; Altera: rax, rcx, rdx, rdi, r8, r11 ;---------------------------------------------------- xor r8, r8 ; zera r8 para contagem de bytes lidos .loop: ; Lendo o arquivo mov rax, SYS_READ ; syscall read syscall cmp rax, 0 jl .done ; se -errno, termina com erro je .return ; se 0, retorna qtd. de bytes lidos .print_line: add r8, rax ; r8+=rax push rdi ; salva rdi (fd) na pilha push rdx ; salva rdx (buf size) na pilha mov rdx, rax ; imprimir até qtd. de bytes lidos mov rax, SYS_WRITE ; syscall write mov rdi, STDOUT ; saída padrão syscall pop rdx ; restaura buffer size pop rdi ; restaura fd jmp .loop .return: mov rax, r8 .done: ret ;---------------------------------------------------- close_file: ;---------------------------------------------------- ; Fecha o arquivo associado a fd ;---------------------------------------------------- ; rdi <- descritor de arquivos ;---------------------------------------------------- ; Altera: rax, rcx, r11 ;---------------------------------------------------- mov rax, SYS_CLOSE ; syscall close syscall ret ;---------------------------------------------------- open_file: ;---------------------------------------------------- ; Abre o arquivo apenas para leitura ;---------------------------------------------------- ; rdi <- caminho do arquivo ; rax -> descritor de arquivo ou erro (-1) ;---------------------------------------------------- ; Altera: rax, rcx, r11 ;---------------------------------------------------- mov rax, SYS_OPEN ; syscall open mov rsi, O_RDONLY ; flag somente leitura mov rdx, 0 ; usado apenas quando um novo arquivo é criado syscall ret ;---------------------------------------------------- ; section .note.GNU-stack noalloc noexec nowrite ;---------------------------------------------------- ``` **Montagem e compilação:** ``` :~$ nasm -felf64 printfile.asm :~$ gcc -Wall -Wextra printfile.o mycat.c -o mycat ``` **Teste:** ``` :~$ ./mycat xxx xxx: No such file or directory :~$ ./mycat /etc/shells # /etc/shells: valid login shells /bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /usr/bin/dash /usr/bin/sh /usr/bin/tmux /bin/zsh /usr/bin/zsh --- /etc/shells: 154 bytes ```
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#33
No description provided.