.section命令定义了数据段output生命了一个標签为output的字符串。.ascii命令表示使用ascii字符声明字符串
如果使用.bss段,则可以在.data段后定义
接着定义了文本段(代码段)。.globl
命令指明后面的标签是外部程序的入口(本例是_start)接着_start是本程序的入口点(GNU汇编器默认的)。
nop是一个空指令XXXX111有什么寓意也做。(在调试时有用)
本程序演示的是使用cpuid指令获取cpu厂商。
$在上下文中有 三种意思:
2.用在内存标记前面表示标记的地址。
3.在gdb调试时是用在寄存器前面,
把output标记的地址放在edi寄存器中,edi寄存器是处理字符串的寄存器(destination)
括号()表示,edi寄存器存储的是内存地址此时是对edi寄存器所存储的地址所在的内存空间
进行处理(间接寻址)。
既然都把结果放在了output所标记的字符串里下面就要显示信息了。本例使用的是
eax包含系统调用指本例是4号系统调用。
ebx表示攵件描述符,1是标准输出
ecx是所要显示字符串的首地址。
edx是要输出的字符串的长度
最后要退出程序,返回os还是使用int $0x80软中断。
ebx存储退出码程序执行后可以在shell中,使用echo $?命令查看退出码
程序看完了,开始汇编(动词)连接。
我们来搞一下把退出码改为100
确实如此。还是改過来吧0通常表示程序正常退出。
上面我们使用的是gnu,binutils软件包里的东西
如果我们想使用gcc来编译呢?
只需把程序入口地址改为main即可,如下
下面開始调试使用gdb。
使用gas在汇编阶段要指定选项-gstabs,才能把源码的很多信息汇编进可执行代码这样才能调试。
**************当然如果使用gcc编译的话也可以在编译阶段用-g选项。 但我调试时出现了错误:
本例以-gstabs调试为例:
我们使用list列举了十行源码,list是用来查看函数的源码的(man gdb)
再然后,我们设置断点对汇编程序进行设置断点,有几个地方可以进行设置:
4.函数执行了指定次数
本例我们就在_start標签处设置断点,上面已经给出了nop这个空指令在调试时,如果
把断点设置成break *_start,就根本不能在断点处停下来
进行单步调试,并且再次查看所有寄存器的值
恢复正常执行(接着执行)continue。
在指定寄存器的时候要使用$符
如果要查看内存(变量)的内容,也可以使用x命令格式为:
z为顯示字段的长度(每隔xx显示):
在查看内存内容的时候,需在内存标记前加&符号表示内存地址。
最后在汇编中连接C库函数,本例连接动态连接库
命令.asciz在字符串后面自动添加空字符(c风格的字符串),因为printf函数需要这样的字符串
.bss段中,使用.lcomm命令定义了12个字节的数据缓冲区。为了把参数传递给printf函数
必须把参数压到栈里,使用pushl命令完成call指令调用printf函数,addl指令把esp(栈顶指针)加8
也即清空了刚刚压入栈的内容最后紦0放入栈中,供exit函数调用
当然也可以使用gcc来编译,只需要把_start标签改为main即可gcc自动连接c函数库。
1.上面红色部分1设置断点时,因为gcc是从main标簽开始所以设置的断点是break *main+1 ,这样就没有错误了.