欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

汇编读写结构化数据

程序员文章站 2024-03-23 14:29:10
...

acsii

  1. 一个字符占一个字节 其中\n、\0等属于也属于一个字符
  2. 32系统中 short与short int型数据占2个字节(16位);int、long int、long型数据占4个字节(32位)
  3. vi编辑模式 u撤销 ctrl+r重做
  4. ls | grep -E "\.s$"

complied

as write-record.s  -o write-record.o --32
as write-records.s  -o write-records.o --32
ld write-record.o write-records.o -o write-records.out -m elf_i386

as read-record.s -o read-record.o --32 --gstabs
as count-chars.s -o count-chars.o --32 --gstabs
as write-newline.s -o write-newline.o --32 --gstabs
as read-records.s -o read-records.o --32 --gstabs

ld read-record.o count-chars.o write-newline.o read-records.o -o read-records.out -m elf_i386

linux.s

# Linux define
  .equ SYS_EXIT, 1
  .equ SYS_READ, 3
  .equ SYS_WRITE, 4
  .equ SYS_OPEN, 5
  .equ SYS_CLOSE, 6
  .equ SYS_BRK, 45

  .equ LINUX_SYSCALL, 0x80

  .equ STDIN, 0
  .equ STDOUT, 1
  .equ STDERR, 2
  
  .equ END_OF_FILE, 0

record.def.s


  .equ RECORD_FIRSTNAME, 0
  .equ RECORD_LASTNAME, 40
  .equ RECORD_ADDRESS, 80
  .equ RECORD_AGE, 320
  
  .equ RECORD_SIZE, 324

write-record.s

 .include "record-def.s"
 .include "linux.s"

 .equ ST_WRITE_BUFFER, 8
 .equ ST_FILEDES, 12

 .section .text
 .globl write_record
 .type write_record, @function
write_record:
 pushl %ebp
 movl %esp, %ebp
 pushl %ebx

 movl $SYS_WRITE, %eax
 movl ST_FILEDES(%ebp), %ebx
 movl ST_WRITE_BUFFER(%ebp), %ecx
 movl $RECORD_SIZE, %edx
 int $LINUX_SYSCALL

 popl %ebx
 movl %ebp, %esp
 popl %ebp
 ret

write-records.s

 .include "linux.s"
 .include "record-def.s"

 .section .data
record1:
 .ascii "Fredrick\0"
 .rept 31
 .byte 0
 .endr

 .ascii "Bartlett\0"
 .rept 31
 .byte 0
 .endr

 .ascii "4242 S Prairie\nTrlsa, OK 55555\0"
 .rept 209
 .byte 0
 .endr

 .long 45

record2:
 .ascii "Marilyn\0"
 .rept 32
 .byte 0
 .endr

 .ascii "Taylor\0"
 .rept 32
 .byte 0
 .endr

 .ascii "2242 S Johannan St\nChicaho, IL 12345\0"
 .rept 203
 .byte 0
 .endr

 .long 29

record3:
 .ascii "Derrick\0"
 .rept 32 
 .byte 0
 .endr

 .ascii "McIntire\0"
 .rept 31
 .byte 0
 .endr

 .ascii "500 W Oakland\nSan Diego, CA 54321\0"
 .rept 206
 .byte 0
 .endr

 .long 36

 .section .data
file_name:
 .ascii "test.dat\0"

 # 文件描述符
 .equ ST_FILE_DESCRIPTOR, -4
 .globl _start

_start:
 movl %esp, %ebp
 subl $4, %esp

 movl $SYS_OPEN, %eax
 movl $file_name, %ebx
 movl $0101, %ecx

 movl $0666, %edx
 int $LINUX_SYSCALL

 movl %eax, ST_FILE_DESCRIPTOR(%ebp)
 
 # wirte 1
 pushl ST_FILE_DESCRIPTOR(%ebp)
 pushl $record1
 call write_record
 addl $8, %esp

 #write 2
 pushl ST_FILE_DESCRIPTOR(%ebp)
 push $record2
 call write_record
 addl $8, %esp

 #write 3
 pushl ST_FILE_DESCRIPTOR(%ebp)
 push $record3
 call write_record
 addl $8, %esp


 movl $SYS_CLOSE, %eax
 movl ST_FILE_DESCRIPTOR(%ebp), %ebx
 int $LINUX_SYSCALL

 movl $SYS_EXIT, %eax
 movl $0, %ebx
 int $LINUX_SYSCALL


count-chars.s

# 对字符进行计数 直到遇到空字符
# 输出字符串地址
# 将计数值返回到%eax
# 
# %ecx --- 字符计数
# %al --- 当前字符
# %edx --- 当前字符地址

 .type count_chars, @function
 .globl count_chars

 .equ ST_STRING_START_ADDRESS, 8

count_chars:
 pushl %ebp
 movl %esp, %ebp

 movl $0, %ecx
 movl ST_STRING_START_ADDRESS(%ebp), %edx

count_loop_begin:
 movb (%edx), %al
 cmpb $0, %al
 je count_loop_end

 incl %ecx
 incl %edx

 jmp count_loop_begin

count_loop_end:
 movl %ecx, %eax
 movl %ebp, %esp
 popl %ebp
 ret

write-newline.s

 .include "linux.s"
 .globl write_newline
 .type write_newline, @function
 .section .data
newline:
 .ascii "\n"
 .section .text
 .equ ST_FILEDES, 0
write_newline:
 pushl %ebp
 movl %esp, %ebp

 movl $SYS_WRITE, %eax
 movl ST_FILEDES(%ebp), %ebx
 movl $newline, %ecx
 # 缓冲区大小
 movl $1, %edx
 int $LINUX_SYSCALL
 movl %ebp, %esp
 popl %ebp
 ret

read-record.s

 .include "record-def.s"
 .include "linux.s"

 .equ ST_READ_BUFFER, 8
 .equ ST_FILEDES, 12

 .section .text
 .globl read_record
 .type read_record, @function
read_record:
 pushl %ebp
 movl %esp, %ebp
 
 pushl %ebx
 movl ST_FILEDES(%ebp), %ebx
 movl ST_READ_BUFFER(%ebp), %ecx
 movl $RECORD_SIZE, %edx
 movl $SYS_READ, %eax
 int $LINUX_SYSCALL

 popl %ebx

#  movl %ebp, %esp
 popl %ebp
 ret

read-records.s

 .include "linux.s"
 .include "record-def.s"

 .section .data
file_name:
 .ascii "test.dat\0"
newline:
 .ascii "\n"
 
 .section .bss
 .lcomm record_buffer, RECORD_SIZE

 .section .text
 .globl _start
_start:
 .equ ST_INPUT_DESCRIPTOR, -4
 .equ ST_OUTPUT_DESCRIPTOR, -8

 movl %esp, %ebp
 subl $8, %esp


 movl $SYS_OPEN, %eax
 movl $file_name, %ebx
 movl $0, %ecx
 movl $0666, %edx
 int $LINUX_SYSCALL

 movl %eax, ST_INPUT_DESCRIPTOR(%ebp)
 movl $STDOUT, ST_OUTPUT_DESCRIPTOR(%ebp)

record_read_loop:
 pushl ST_INPUT_DESCRIPTOR(%ebp)
 pushl $record_buffer
 call read_record
 addl $8, %esp

 cmpl $RECORD_SIZE, %eax
 jne finished_reading

 pushl $RECORD_FIRSTNAME + record_buffer
 call count_chars
 addl $4, %esp
 movl %eax, %edx
 movl ST_OUTPUT_DESCRIPTOR(%ebp), %ebx
 movl $SYS_WRITE, %eax
 movl $RECORD_FIRSTNAME + record_buffer, %ecx
 int $LINUX_SYSCALL 

 push ST_OUTPUT_DESCRIPTOR(%ebp)
 call write_newline
 addl $4, %esp
 jmp record_read_loop

finished_reading:

 movl $SYS_WRITE, %eax
 movl ST_OUTPUT_DESCRIPTOR(%ebp), %ebx
 movl $newline, %ecx
 movl $1, %edx
 int $LINUX_SYSCALL
 

 movl $SYS_EXIT, %eax
 movl $0, %ebx
 int $LINUX_SYSCALL