读书笔记:machine-level representation of program

1. 程序编码, 本章主要介绍了汇编和C的相互转化和理解, 本章的的意义在于看到C能翻译成汇编,看到汇编能翻译成C。 
 

 程序本质是一系列的ISA(instruction set architecture)

许多在汇编中可见的东西在C中都看不到了,比如 PC(program count 用来指向下一条执行的指令)在汇编中用%eip表示,C中是看不到的。

下面是一个c和汇编机器语言的转变的例子:

int accum = 0;
int sum(int x, int y){
    int t=x+y; 
    accum += t; 
    return t;
}

unix> gcc -O1 -S code.c

在调用gcc -S之后产生的汇编文件中会有很多  .file  .txt之类以点开头的行,这些点的意思其实就是告诉编译器这些行可以忽略。

sum:
  pushl   %ebp
  movl    %esp, %ebp
  movl    12(%ebp), %eax
  addl    8(%ebp), %eax
  addl    %eax, accum  //仍然显示变两名,因为还不确定,如果有main函数调用,则会变成一个固定地址,例如 0x804a018   
  popl    %ebp
  ret

unix> gcc -O1 -c code.c

55 89 e5 8b 45 0c 03 45 08 01 05 00 00 00 00 5d c3

如果需要查看机器代码的内容,我们j可以使用 objdump反编译(disassemble)把机器代码反向编成汇编

unix> objdump -d code.o

机器代码和汇编的一些对照

a)单个指令在机器码中长1到15个字节


AT&T differ Intel Assemble

  • .  The Intel code omits the size designation suffixes. We see instruction movinstead ofmovl.

    char (b), short(w), float(s), long double(t) , all others are (l)

  • .  The Intel code omits the ‘%’ character in front of register names, using espinstead of%esp.

  • .  The Intel code has a different way of describing locations in memory, for example ‘DWORD PTR[ebp+8]’rather than ‘8(%ebp)’.

  • .  Instructions with multiple operands list them in the reverse order. This can be very confusing whenswitching between the two formats. 



AT&T 有几个比较重要的概念,理解了这些概念,然后对照具体的指令,基本就可以读懂汇编了

1. 所有的命令都有后缀, b(byte)w(word)l(quad)比如movb movw movl, 另外还有补0或者补符号的,比如movz, movs

2. 操作的数据有三类,一类临时数据,以$打头的数据,比如$123, 第二类是register,%eax,第三类是内存,都有个括号比如7(%eax,%eax,4)

3. 四个操作位, 后面好多针对不同标志位的cmp,test, jmp

4. mov lea的不同:一个是mov地址指向的内容,lea只是mov地址

CF:Carry Flag. The most recent operation generated a carry out of the mostsignificant bit. Used to detect overflow for unsigned operations.

ZF:Zero Flag. The most recent operation yielded zero.

SF:Sign Flag. The most recent operation yielded a negative value.

OF:Overflow Flag. The most recent operation caused a two’s-complementoverflow—either negative or positive. 



C语言的一些特性:

1 函数的调用

c语言和汇编的转化有个重要的概念叫stack frame,通过它C实现了函数之间的调用。

对stack的操作有call,leave,ret, 寄存器在此时也被分成两种一种是caller save,另一种是callee save,分别用来保存两者的状态,当然stack还是必须的因为寄存器可能不够用,还有一些比如必须给一些local variable一些地址,所有必须放在stack里。

对于递归调用和其他调用一致。


2. 数组

C语言对数组的表示非常简单,就是一段连续的内存,所以对应到汇编要访问数组元素也很简单是movl (%edx,%ecx,4),%eax 。

多维数组(nested array)访问可以对应到一维数组的访问,C语言如果要分配动态数组就要使用malloc 或者 calloc(calloc  size*number, 且都初始成0)



3. struct  union,在内存中数据对齐的问题。



GDB的使用,这里列举了一些过去所不了解的GDB的命令,原来GDB如此的强大,会汇编有很深厚的解释

编译器会优化代码,这导致很难建立c和机器语言之间的map,所以我们最好要熟悉常用的优化办法。

1. break sum      // Set breakpoint at entry to functionsum    

2. break *0x8048394     //Set breakpoint at address 0x8048394    

3. delete 1          // Delete breakpoint 1

4. stepi   4 //Execute four instructions


5. disas   // Disassemble current function

6. disas sum //Disassemble functionsum

7.disas 0x8048397 //Disassemble function around address0x8048397    

8. disas 0x8048394 0x80483a4     //Disassemble code within specified address range    

9. print /x $eip      //Print program counter in hex    

10. print *(int *) 0xfff076b0    //Print integer at address0xfff076b0

11. info frame     //Information about current stack frame    

12. info registers     //Values of all the registers



address-space layout randomization    : 避免stack的地址被预测到然后被攻击。

对于浮点数的处理,汇编有一套和整数相似的指令集合,在早期的intel的CPU当中会有一个独立的芯片来做浮点运算。









    

你可能感兴趣的:(读书笔记:machine-level representation of program)