IA-32 汇编

    看《深入了解计算机系统》时,看到第三章——程序的机器级表示时就稀里糊涂了,汇编是汇编,不像以前学的8051的汇编,但是思想一样。


     拿了一本《汇编语言程序设计》看,讲的就是IA-32(IntelArchitecture,32-bit)系列的汇编(32位)。为的是搞懂书上大概写了什么。


     最底层,处理器在出厂的时候就已经定义好的二进制代码操作数据,这些代码为指令码。IA-32指令码的格式构成为可选的指令前缀,操作码,可选的修饰符,可选的数据元素。如C745 FC 01 00 00 00,C7 操作码为将值传送到内存位置,45 FC为内存位置,从EBP寄存器中的值45指向内存位置开始的4字节,此位置值为01 00 00 00,小尾数读法,就像格列佛游记中的鸡蛋究竟从哪边敲起一样,没必要追究那么多,从后面开始读起。其实也不必太纠结上面那条语句,在你写简简单单的helloworld的时候,会发现这语句真的是给机器读的。

 

    所以有了高级语言,其中的编译型语言编译生成的目标文件里面就是上述的那些指令码。那么难懂的语言用了push,mov这些简单好记的符号来标记,就成了汇编了。


     cpu里面有寄存器,因为每次访问数据都往内存跑的话那很费劲,寄存器有多种,通用、段。指令指针、浮点数据、控制、调试寄存器:


常用的有通用寄存器:

EAX   用于操作数和结果数据的累加器

EBX   指向数据内存段中的数据的指针

ECX   字符串和循环操作的计数器,loop根据ecx值来结束循环

EDX   I/O指针

EDI    字符串操作的目标的数据指针

ESI    字符串操作的源的数据指针

ESP   堆栈指针

EBP   堆栈数据指针


汇编程序的组成:数据段、bss段、文本段,这部分略过。


常用指令

MOV一个mov又有很多种方式

movl 32位长字值 movw 16位    movb  8位

movl $12 , %eax  将12传到eax寄存器,$表示立即数


有一种变址内存模式

array:

     .int 1,2,3,4,5,6

movl$1 ,%edi

movl array(,%edi,4),%eax

将array标签开始的第二个4字节变址值加载到eax中,这里的数组首位也是0。


movl %edx,(%edi)

没有括号的时候,就是把ebx寄存器的值加载到edi中,有了括号之后,是把ebx寄存器的值加载到edi包含的内存位置。看到这里是否似曾相识——指针。


movl %edx,4(%edi)   edi指向位置四个字节之后,同指针++。

movl %edx,-4(%edi)  同上 ,同指针- -。


inc 递增1   dec递减1

 

cmov有很多指令对


数据交换指令

xchg 两个通用寄存器之间或者寄存器和内存位置之间交换数据值。

后面一些书上没看到,略过。


压入和弹出数据

pushl/pushw l用于长字  w用于字

pushl %ecx将ecx寄存器的32位值压入堆栈中。


pop就是弹出了


类似goto语句的jump

jmp 标签名  相当于跳转

而条件跳转的指令更是多,JA 如果大于跳转 JGE 大于或等于跳转

JLE 小于或等于 JZ为零跳转  JNZ非零跳转


循环 loop

这就回到之前的ECX寄存器,当其为0的时候,循环终止。


最后以一段冒泡的汇编代码结束,省去一些格式

array:
 .int 1,3,5,2,10,6,7,4,8,9

movl $array,%esi             #将数组加载到esi
movl $9, %ecx                #9加载到ecx寄存器   因为是冒泡算法 所以有两层循环
movl $9, %ebx                #同上

loop:
     movl (%esi),%eax        #因为没有所谓数组的概念,所以拿的是esi的首地址,也就是
                             #第一个元素  加载到eax

     cmp %eax, 4(%esi)       #esi指向的地址四个字节之后 为第二个元素  比较大小
     jge skip                #大于 跳转到skip标签
     xchg %eax,4(%esi)       #不大于 交换值 就是冒泡
     movl %eax,(%esi)        #把小的数发到第一个元素位置 继续执行skip

skip:
add $4,%esi                  #大于的情况   取esi下一个元素
dec %ebx                     #ebx减一 ,循环一次了
jnz loop                     #不为零  跳转loop循环
dec %ecx                     #ecx 减一  外层循环 
jz end                       #ecx为零   程序借宿
movl $array,%esi             #每一次内层循环结束  又重新开始 
movl %ecx,%ebx
jmp loop

end:
movl $1,%eax
movl $0,%ebx
int $0x80                    #中断

     读懂上面的,再回去看简单的程序就不会那么吃力了。包括JVM的一些代码好像也是这样,当时看得稀里糊涂。

    写编译器的那些人,真的很厉害。






    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iaiti

赏顿早餐钱~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值