汇编读写结构化数据

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$"
  5. pushl $RECORD_FIRSTNAME + record_buffer中,RECORD_FIRSTNAME和record_buffer都是常数,前者是直接常数,通过.equ指令创建,后者是有汇编程序自动定义为标签(其值是紧随其后的数据的起始地址)。由于两者都是汇编程序知道的常数,因此汇编程序在实际汇编程序时能将两者相加,这样整个指令就只是立即寻址方式的单个常量入栈。
    RECORD_FIRSTNAME常量是一条记录从起始地址到名字段之间的字节数。record_buffer是用于保存记录的缓冲区的名字。将以上两者相加,我们就可获得存储在record_buffer中记录的名字段地址。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值