C/C++知识点之C指针原理(21)-C指针基础-AT&T汇编
小标 2019-02-19 来源 : 阅读 581 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之C指针原理(21)-C指针基础-AT&T汇编,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之C指针原理(21)-C指针基础-AT&T汇编,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之C指针原理(21)-C指针基础-AT&T汇编

helloworld-高级版


.section .data#初始化的变量
output:
   .ascii "hello,world\n"
   #要打印的字符串,.data为初始化值的变量。output是标签,指示字符串开始的位置,ascii为数据类型
.section .bss#未初始化的变量,由0填充的缓冲区
   .lcomm num,20
   #lcomm为本地内存区域,即本地汇编外的不能进行访问。.comm是通用内存区域。
.section .text#汇编语言指令码
   .globl _start#启动入口
   _start:
   movl $4,%eax#调用的系统功能,4为write   
   movl $output,%ecx#要打印的字符串
   movl $1,%ebx#文件描述符,屏幕为1   
   movl $12,%edx#字符串长度
   int $0x80#显示字符串hello,world
   
   movl $0,%eax
   movl $num,%edi
   movl $65,1(%edi)#A 的ascii
   movl $66,2(%edi)#B 的ascii 
   movl $67,3(%edi)#C 的ascii 
   movl $68,4(%edi)#D 的ascii
   movl $10,5(%edi)#\n的ascii 
   
   movl $4,%eax#调用的系统功能,4为write    
   movl $num,%ecx#要打印的字符串  
   movl $1,%ebx#文件描述符,屏幕为1   
   movl $6,%edx#字符串长度
   int $0x80#显示字符串ABCD
         
   movl $1,%eax#1为退出
   movl $0,%ebx#返回给shell的退出代码值


   int $0x80#内核软中断,退出系统
   
   
   


效果及调试, -gstabs用于生成调试信息


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ as -gstabs -o hello.o hello.s


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ ld -o hello hello.o


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ ./hello


hello,world


ABCD


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ gdb hello


GNU gdb (GDB) 7.1-ubuntu


Copyright (C) 2010 Free Software Foundation, Inc.


License GPLv3+: GNU GPL version 3 or later <//gnu.org/licenses/gpl.html>;


This is free software: you are free to change and redistribute it.


There is NO WARRANTY, to the extent permitted by law.  Type "show copying"


and "show warranty" for details.


This GDB was configured as "x86_64-linux-gnu".


For bug reporting instructions, please see:


<//www.gnu.org/software/gdb/bugs/>;...


Reading symbols from /home/deepfuture-lx/private/mytest/hello...done.


(gdb) list


1 .section .data#初始化的变量


2 output:


3    .ascii "hello,world\n"


4    #要打印的字符串,.data为初始化值的变量。output是标签,指示字符串开始的位置,ascii为数据类型


5 .section .bss#未初始化的变量,由0填充的缓冲区


6    .lcomm num,20


7    #lcomm为本地内存区域,即本地汇编外的不能进行访问。.comm是通用内存区域。


8 .section .text#汇编语言指令码


9    .globl _start#启动入口


10    _start:


(gdb) run


Starting program: /home/deepfuture-lx/private/mytest/hello 


hello,world


ABCD


Program exited normally.


(gdb) 


linux-汇编-调用C库函数


1、使用GCC编译


.section .data
  output:
  .asciz "//deepfuture.iteye.com\n"  
.section .text
   .global  main
   main:
   push $output
   call printf
   addl $4,%esp
   push $0
   call exit


gcc -o  test test.s


./test


//deepfuture.iteye.com
2、使用汇编器编译,使用动态链接-dynamic-linker,要求后跟SO库,可使用find / -name ld*.so来寻找链接库,每个LINUX版本不一样,链接库不一样,笔者用的是puppy linux,链接库名为ld-linux.so.2


.section .data
  output:
  .asciz "//deepfuture.iteye.com\n"  
.section .text
   .global  _start
   _start:
   push $output
   call printf
   addl $4,%esp
   push $0
   call exit


as -o test.o test.s


ld -lc -dynamic-linker /lib/ld-linux.so.2 -o test test.o


./test


//deepfuture.iteye.com


汇编中通用寄存器的目的


1、EAX和AX:累加器,所有的I/O指令用它来与外部设备传送信息


2、EBX和BX:在计算存储单元地址时常用作基地址寄存器


3、ECX和CX:保存计数值


4、EDX和DX:做四字或二字运算时,可以把EDX(DX)和EAX(AX)组合在一起存放一个四字或二字长的数据,在对某些I/O操作时,DX可以放I/O的端口地址


5、ESP和SP:堆栈栈顶指针。


6、EBP和BP:基址寄存器


7、ESI和SI:源变址


8、EDI和DI:目的变址


LINUX/UNIX一般 都安装了binutils,如果没有安装,在UBUNTU下可以使用apt-get


1.deepfuture@deepfuture-laptop:~$ sudo apt-get install binutils


[sudo] password for deepfuture: 


正在读取软件包列表... 完成


正在分析软件包的依赖关系树       


正在读取状态信息... 完成       


binutils 已经是最新的版本了。


下列软件包是自动安装的并且现在不需要了:


  libany-moose-perl libtest-exception-perl libmouse-perl gcc-4.4-multilib


  ibus-pinyin-db-open-phrase libclass-c3-perl libdata-optlist-perl


  libclass-c3-xs-perl libparams-util-perl lib64gomp1 libmro-compat-perl


  lib64gcc1 pinyin-database libsub-install-perl libc6-amd64 libc6-dev-amd64


  gcc-multilib libclass-method-modifiers-perl libsub-uplevel-perl lib64stdc++6


  libsub-exporter-perl libalgorithm-c3-perl


使用'apt-get autoremove'来删除它们


升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。


2.也可以在其主页上用源代码安装


//www.gnu.org/software/binutils/


1、调试hello,要求编译时指定了-gstabs选项


2、运行hello


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ ./hello


hello,world


ABCD


3、用gdb打开hello


deepfuture-lx@deepfuture-lx-desktop:~/private/mytest$ gdb hello


GNU gdb (GDB) 7.1-ubuntu


Copyright (C) 2010 Free Software Foundation, Inc.


License GPLv3+: GNU GPL version 3 or later <//gnu.org/licenses/gpl.html>;


This is free software: you are free to change and redistribute it.


There is NO WARRANTY, to the extent permitted by law.  Type "show copying"


and "show warranty" for details.


This GDB was configured as "x86_64-linux-gnu".


For bug reporting instructions, please see:


<//www.gnu.org/software/gdb/bugs/>;...


Reading symbols from /home/deepfuture-lx/private/mytest/hello...done.


4、列出源代码


(gdb) list


warning: Source file is more recent than executable.


1 .section .data#初始化的变量


2 output:


3    .ascii "hello,world\n"


4    #要打印的字符串,.data为初始化值的变量。output是标签,指示字符串开始的位置,ascii为数据类型


5 .section .bss#未初始化的变量,由0填充的缓冲区


6    .lcomm num,20


7    #lcomm为本地内存区域,即本地汇编外的不能进行访问。.comm是通用内存区域。


8 .section .text#汇编语言指令码


9    .globl _start#启动入口


10    _start:


(gdb) list


11    movl $4,%eax#调用的系统功能,4为write   


12    movl $output,%ecx#要打印的字符串


13    movl $1,%ebx#文件描述符,屏幕为1   


14    movl $12,%edx#字符串长度


15    int $0x80#显示字符串hello,world


16    


17    movl $0,%eax


18    movl $num,%edi


19    movl $65,1(%edi)#A 的ascii


20    movl $66,2(%edi)#B 的ascii 


5、设置断点


(gdb) break 17


Breakpoint 1 at 0x4000c6: file hello.s, line 17.


6、运行至断点


(gdb) run


Starting program: /home/deepfuture-lx/private/mytest/hello 


hello,world


Breakpoint 1, _start () at hello.s:17


7、运行下条语句


17    movl $0,%eax


(gdb) next


18    movl $num,%edi


8、显示所有寄存器的值


(gdb) info registers


rax            0x0 0


rbx            0x1 1


rcx            0x60011c 6291740


rdx            0xc 12


rsi            0x0 0


rdi            0x0 0


rbp            0x0 0x0


rsp            0x7fffffffe2d0 0x7fffffffe2d0


r8             0x0 0


r9             0x0 0


r10            0x0 0


r11            0x0 0


r12            0x0 0


r13            0x0 0


r14            0x0 0


r15            0x0 0


rip            0x4000cb 0x4000cb <_start+27>

eflags         0x202 [ IF ]

cs             0x33 51

ss             0x2b 43

ds             0x0 0

es             0x0 0

fs             0x0 0

---Type <return> to continue, or q <return> to quit---

gs             0x0 0

(gdb) next

19    movl $65,1(%edi)#A 的ascii


9、按十六进制格式输出edi寄存器的值。/x表示16进制,/d表示10进制,/t表示二进制


(gdb) print/x $rdi


$3 = 0x600128


10、显示所有寄存器值


(gdb) info registers

rax            0x0 0

rbx            0x1 1

rcx            0x60011c 6291740

rdx            0xc 12

rsi            0x0 0

rdi            0x600128 6291752

rbp            0x0 0x0

rsp            0x7fffffffe2d0 0x7fffffffe2d0

r8             0x0 0

r9             0x0 0

r10            0x0 0

r11            0x0 0

r12            0x0 0

r13            0x0 0

r14            0x0 0

r15            0x0 0

rip            0x4000d0 0x4000d0 <_start+32>

eflags         0x202 [ IF ]

cs             0x33 51

ss             0x2b 43

ds             0x0 0

es             0x0 0

fs             0x0 0

---Type <return> to continue, or q <return> to quit--- 

gs             0x0 0

(gdb) next

20    movl $66,2(%edi)#B 的ascii 


11、显示某个内存位置的值,x/nyz,其中n为字段数,y为格式(c为字符,d为10进制,x为16进制),z为字段长度(b为字节,n为16位字,w为32位字)


(gdb) next


21    movl $67,3(%edi)#C 的ascii 


(gdb) x/3cb &num


0x600128 <num>: 0 '\000'65 'A' 66 'B'


(gdb) next


22    movl $68,4(%edi)#D 的ascii


(gdb) next


23    movl $10,5(%edi)#\n的ascii 


(gdb) next


25    movl $4,%eax#调用的系统功能,4为write    


(gdb) x/4cb &num


0x600128 <num>: 0 '\000'65 'A' 66 'B'67 'C'


12、退出gdb


(gdb)quit


linux-汇编静态符号
.equ 符号名 值


比如


.equ PI 3.1415


使用方式 为:


movl $PI,%eax


汇编数据类型


.ascii 文本字符串


.asciz 以空字符结尾的文本字符串


.byte 字节值


.double 双精度符点数


.float 单精度符点数


.int 32位整数


.long 64位整数


.octa 16字节整数


.quad 8字节整数


.short 16位整数


.single 单精度整数与float相同


汇编传送指令


传送数据元素


movl:32位长度


movw:16位长度


movb:8位长度


比如:


movl 源,目标


汇编-多值内存位置访问(1)


.section .data
  myvalue:
     .byte 67,68,69,70,0
  mygs:
     .asciz "%s\n"
   
.section .text
.globl main
   main:
    movl $myvalue,%ecx
    inc %ecx#本来应输出CDEF,68代表D
    push %ecx
    push $mygs    
    call printf
    push $0
    call exit


        deepfuture@deepfuture-laptop:~/private/mytest$ gcc -o test12 test12.s
deepfuture@deepfuture-laptop:~/private/mytest$ ./test12


DEF


deepfuture@deepfuture-laptop:~/private/mytest$ 


deepfuture@deepfuture-laptop:~/private/mytest$ gcc -o test12 test12.s


deepfuture@deepfuture-laptop:~/private/mytest$ ./test12


E


deepfuture@deepfuture-laptop:~/private/mytest$ 


.section .data
  myvalue:
     .byte 67,68,69,70,0
  mygs:
     .asciz "%c\n"
   
.section .text
.globl main
   main:
    #基地址(偏移地址[必须为寄存器],数据元素变址,数据元素长度[必须为寄存器],)
    #基地址+偏移地址+数据元素变址数据元素长度
    movl $2,%ecx
    movl myvalue(,%ecx,1),%ebx #将myvalue的变址为2,长度为1的数据值移到ebx中
    push %ebx
    push $mygs    
    call printf
    push $0
    call exit
       
    
    .section .data
  myvalue:
     .byte 67,68,69,70,0
  mygs:
     .asciz "%c\n"
  mygss:
     .asciz "%s\n"
.section .text
.globl main
   main:
    #以下为传数值
    #深未来技术,//deepfuture.iteye.com
    #基地址(偏移地址[必须为寄存器],数据元素变址,数据元素长度[必须为寄存器],)
    #基地址+偏移地址+数据元素变址数据元素长度
    movl $2,%ecx
    movl myvalue(,%ecx,1),%ebx #将myvalue的变址为2,长度为1的数据值移到ebx中
    push %ebx
    push $mygs    
    call printf
    #以下为传地址
    movl $2,%ecx
    movl $myvalue,%ebx#传myvalue的地址,变量前加上$
    push %ebx
    push $mygss    
    call printf 
    #以下为传数值
    movl $2,%ecx
    movl myvalue,%ebx#传myvalue第一个内存位置的数值
    push %ebx
    push $mygs    
    call printf    
    #以下为传地址,mov %eax,(%ebx)表示把eax值复制到寄存器ebx所代表内存位置中,寄存器中存放着地址
    movl $71,%edx
    movl $myvalue,%eax;
    movb %dl,2(%eax)#eax指向位置后的第2个字节,将69改为71
    movl $myvalue,%ebx
    push %ebx
    push $mygss    
    call printf  
    push $0
    call exit


deepfuture@deepfuture-laptop:~/private/mytest$ gcc -o test12 test12.s


test12.s: Assembler messages:


test12.s:0: Warning: end of file not at end of a line; newline inserted


deepfuture@deepfuture-laptop:~/private/mytest$ ./test12


E


CDEF


C


CDGF


deepfuture@deepfuture-laptop:~/private/mytest$ 


汇编的movl使用


.section .data
  myvalue:
    .int 67
   
.section .text
.globl main
   main:
    movl $myvalue,%ecx
    push $myvalue
    call printf
    push $0
    call exit


deepfuture@deepfuture-laptop:~/private/mytest$ gcc -o test12 test12.s


deepfuture@deepfuture-laptop:~/private/mytest$ ./test12


Cdeepfuture@deepfuture-laptop:~/private/mytest$ 

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程