AT&T汇编语言学习:利用c库、文件读写

AT&T汇编、调用C库函数、读/写文件
d0321:更新读文件代码(图片)以后会更新代码版。
d0329:汇编文本读取、简单动画。
================================================

本文是利用AT&T风格调用C库,来读取文件内容。(如果安装的是64位的linux,需要安装32位的C库。并在利用gcc编译的时候加入-m32指令。)
64位利用32位库的编译指令如下:(-ggdb是加入gdb调试信息)

gcc -m32 -ggdb readfile.s -o readfile
  • 利用C库函数fscanf读文件

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

  • GDB调试代码

    • 查看寄存器中的值
        info reg

    这里写图片描述

    • 查看内存中的值
        x/nfu <addr>
    • n表示要显示的内存单元的个数。
    • f表示显示方式, 可取如下值:
      x 按十六进制格式显示变量。 d 按十进制格式显示变量。
      u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。
      c 按字符格式显示变量。f 按浮点数格式显示变量。
    • u表示一个地址单元的长度,可取下值
      b表示单字节,h表示双字节,w表示四字节,g表示八字节。

    这里写图片描述

  • 汇编语言完成简单文本动画

在实现了基本的文件读取功能后,利用汇编语言制作了简单的动画(用空格实现)
该程序的基本流程如下:
这里写图片描述

.code32
.section    .rodata 

#参数定义
mode:
    .string "r"
sreturn:
    .string "Read file success"
freturn:
    .string "Read file failed"
space:
    .string " "
printstring:
    .string "%s"
colorRed:
    .string "\033[31m"
colorYellow:
    .string "\033[33m"
colorGreen:
    .string "\033[36m"
nomalEnd:
    .string "\033[0m"
colorType:
    .string "%s%s%s"
clear:
    .string "clear"
tmp:
    .string "@"


#代码部分
.text


#animation
.globl  animation
.type   animation, @function
animation:
    pushl   %ebp        
    movl    %esp, %ebp

    subl    $200, %esp  #设置该函数的栈区为ebp-200
    xorl    %eax, %eax  #clear %eax
    movl    $0,-108(%ebp)    #设置刷新10次

file_open:
    pushl   $mode  #将文件读取模式压入栈
    pushl   8(%ebp)
    call    fopen 
    addl    $8, %esp  #清除上面压栈的mode和path

check_open:
    cmpl    $0, %eax #eax中接着的是返回值
    je  read_fail #如果无法读取就跳转


read_sus:
    movl    %eax, -104(%ebp) #将文件指针保存在-104

    pushl   $sreturn #输出成功读取文件提示
    call    puts
    addl    $4, %esp #清除上面压栈的sreturn

    pushl   $clear  #将clear指令压栈
    call    system  #调用system系统函数,用来清屏
    addl    $4,%esp #清除上面压栈的一个参数

read_one_line:
    pushl   -104(%ebp)  #这里是把ebp-104里面存的的值压进去(fp)   
    pushl   $200        #将fgets的第二个参数压栈    
    leal    -100(%ebp), %eax  #将从文件中读取的数据保存到ebp-100
    pushl   %eax        #这里是把ebp-100的这个值(地址压进去)
    call    fgets
    addl    $12, %esp   #清除压栈参数

check_EOF:
    pushl   -104(%ebp)  #这里是把ebp-104里面存的的值压进去(fp)
    call    feof
    addl    $4, %esp   #清除上面压栈的一个参数
    cmpl    $0,%eax    #判断返回值
    jne close_file

    movl    -108(%ebp),%ebx  #将刷新参数读到ebx
print_space:    

    #pushl  $tmp
    #call   printf
    #addl   $4,%esp

    cmpl    $0,%ebx   
    je  print_text #如果已经打印完了就开始输出数据
    pushl   $space   #打印空格
    pushl   $printstring
    call    printf
    addl    $8,%esp  #清理压栈
    subl    $1,%ebx  #循环参数减一
    jmp print_space

print_text: 
    leal    -100(%ebp), %eax  #将刚才读出来的数据压栈,准备输出
    pushl   $nomalEnd
    pushl   %eax    
    pushl   $colorYellow
    pushl   $colorType          
    call    printf
    addl    $4, %esp   #清除上面压栈的一个参数
    jmp     read_one_line


close_file:
    pushl   -104(%ebp)   #把文件指针压栈
    call    fclose       #关闭文件
    addl    $4, %esp     #清除上面压栈的一个参数

    movl    $0, -104(%ebp) #清空文件指针

    movl    -108(%ebp),%ebx  #当缓冲空格已经结束
    cmp $30,%ebx   
    je  end_main

    addl    $1,%ebx    #刷新剩余次数加一
    movl    %ebx,-108(%ebp)  #保存起来
    pushl   $80000   #sleep参数
    call    usleep
    pushl   $clear   #清屏
    call    system
    addl    $8,%esp
    jmp     file_open

read_fail:
    pushl   $freturn #输出读取失败文件提示
    call    puts
    addl    $4, %esp #清除上面压栈的一个参数


end_main:
    leave
    ret


#main
.section    .rodata
welcomemsg:
    .string "================================================================\n                     Welcome!\n Please Input the filename you wantta play!\n================================================================\n"
askagain:
    .string "again?(y/n)"
stringType:
    .string "%s"
yes:
    .string "y"
no:
    .string "n"
inttype:    
    .string "%d"
.globl  main
.type   main, @function

main:
    pushl   %ebp        
    movl    %esp, %ebp

    subl    $50,%esp   #主函数栈区

    pushl   $welcomemsg
    call    printf
    addl    $4,%esp

    leal    -4(%ebp),%eax #输入文件路径
    pushl   %eax
    pushl   $stringType
    call    scanf
    addl    $8,%esp

start:
    leal    -4(%ebp),%eax
    pushl   %eax
    call    animation #播放开启动画
    addl    $4,%esp

ask:    
    pushl   $askagain #again?
    call    printf
    addl    $4,%esp

    leal    -14(%ebp), %eax #y/n
    pushl   %eax
    pushl   $stringType
    call    scanf
    addl    $8, %esp

    subl    $16, %esp #is y?
    leal    -14(%ebp), %eax
    pushl   %eax
    pushl   $yes
    call    strcmp
    addl    $24, %esp
    cmpl    $0,%eax
    je  start

    subl    $16, %esp #is n?
    leal    -14(%ebp), %eax
    pushl   %eax
    pushl   $no
    call    strcmp
    addl    $24, %esp
    cmpl    $0,%eax
    je  endmain
    jmp ask

endmain:
    leave
    ret

运行截图:(其中1文件见下)
这里写图片描述
为动画效果,不好截图,可以将源码拷贝运行一次。
这里写图片描述

文件1

           ###########
         #             #   
        #               #
    ###  #             #  ### 
  #     # #           # #     #
 #                             #       
#                               #
 #                             #
  #############################

文件2

====    ====    ====    ||||
====    ====    ====    ||||
====    ====            ||||
====    ====    ====    ||||
============    ====    ||||
============    ====    ||||
====    ====    ====
====    ====    ====    ||||
====    ====    ====    ||||

转载于:https://www.cnblogs.com/he11o-liu/p/7503256.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值