前言:
如今你们对“c语言和e语言”大约比较珍视,同学们都想要知道一些“c语言和e语言”的相关知识。那么小编在网络上搜集了一些对于“c语言和e语言””的相关内容,希望大家能喜欢,看官们一起来学习一下吧!通过改写示范程序Ch02_05,重点掌握以下内容:1、C语言声明固定大小整数类型的方式;2、movzbl、movzwl、movsbp、movswq、movslq等零扩展和有符号扩展传送指令;3、gdb中查看“寄存器+偏移量”指向的内存地址中不同宽度的数值;4、利用gdb查看C语言变量与寄存器、内存地址之间数值传递情况,采用“寄存器+偏移量”的方式进行数值传递;5、反汇编。
本程序的目标为:设定8个变量a、b、c、d、e、f、g、h,其中a、e为1个字节,b、f为1个字,c、g为1个双字,d、h为1个四字。计算prod1=prod2=a*b*c*d*e*f*g*h,quo1=quo2=(a+b+c+d)/(e+f+g+h),rem1=rem2=(a+b+c+d)%(e+f+g+h)(%为求余数),prod1、quo1、rem1用C语言计算求出,prod2、quo2、rem2用汇编语言计算。
关于字节、字、双字、四字的位数、C语言定义、汇编指令表示的对应关系如下:
大小
中文表达
英文表达
c语言定义
汇编指令后缀
8bit
字节
byte
char、int8_t
b
16bit
字
word
short、int16_t
w
32bit
双字
double words
int、int32_t
l
64bit
四字
quad words
long
q
一、编辑c语言如下:
#include<stdio.h>
#include<inttypes.h> /*此头文件用于指定固定大小变量*/
extern int64_t IntegerMul_(int8_t a,int16_t b,int32_t c,int64_t d,int8_t e,int16_t f,int32_t g,int64_t h); /*引入外部汇编变量IntegerMul_ */
extern uint64_t UnsignedDiv_(uint8_t a,uint16_t b,uint32_t c,uint64_t d,uint8_t e,uint16_t f,uint32_t g,uint64_t h,uint64_t* quo2,uint64_t* rem2); /*引入外部汇编变量UnsignedDiv_ */
void IntegerMul(void)
{
int8_t a=2;
int16_t b=-3;
int32_t c=8;
int64_t d=4;
int8_t e=3;
int16_t f=-7;
int32_t g=-5;
int64_t h=10;
printf("Results for IntegerMul\n a=%d b=%d c=%d d=%ld e=%d f=%d g=%d h=%ld\n",a,b,c,d,e,f,g,h);
int64_t prod1=a*b*c*d*e*f*g*h; /*用c语言计算乘积*/
int64_t prod2=IntegerMul_(a,b,c,d,e,f,g,h); /*用汇编计算乘积*/
printf(" prod1=%ld\n prod2=%ld\n",prod1,prod2);
}
void UnsignedIntegerDiv(void)
{
uint8_t a=12;
uint16_t b=17;
uint32_t c=71000000;
uint64_t d=90000000000;
uint8_t e=101;
uint16_t f=37;
uint32_t g=25;
uint64_t h=5;
uint64_t quo1,rem1;
uint64_t quo2;
uint64_t rem2;
int rc;
printf("Results for UnsignedIntegerDiv\n a=%u b=%u c=%u d=%lu e=%u f=%u g=%u h=%lu\n",a,b,c,d,e,f,g,h);
quo1=(a+b+c+d)/(e+f+g+h); /*C语言计算商*/
rem1=(a+b+c+d)%(e+f+g+h); /*C语言计算余数*/
printf(" quo1=%lu ,rem1=%lu\n",quo1,rem1);
rc=UnsignedDiv_(a,b,c,d,e,f,g,h,&quo2,&rem2); /*用汇编继续除法计算,并且返回是否正确计算的值*/
if(rc==0)
printf("警告:除数不能为0");
else
printf("quo2=%lu, rem2=%lu\n",quo2,rem2);
}
int main(void)
{
IntegerMul();
UnsignedIntegerDiv();
return 0;
}
二、编辑汇编程序如下:(错误程序)
.text
.global IntegerMul_
.global UnsignedDiv_
IntegerMul_:
movsbq %dil,%rdi
movswq %si,%rsi
imul %rsi,%rdi
mov %rdi,%rax
movslq %edx,%rdx
imul %rcx,%rdx
imul %rdx,%rax
movsbq %r8b,%r8
movswq %r9w,%r9
imul %r9,%r8
imul %r8,%rax
movslq 0x38(%rsp),%rdx
imul 0x40(%rsp),%rdx
imul %rdx,%rax
ret
UnsignedDiv_:
movzbq %dil,%rdi
movzwq %si,%rsi
add %rsi,%rdi
mov %edx,%edx
add %rcx,%rdx
add %rdx,%rdi
mov %rdi,%rax
xor %rdx,%rdx
movzbq %r8b,%r8
movzwq %r9w,%r9
add %r9,%r8
mov 0x38(%rsp),%edi
mov 0x40(%rsp),%rsi
add %rsi,%rdi
add %rdi,%r8
jne DivOK
xor %rax,%rax
jmp Done
DivOK:
div %r8
mov 0x48(%rsp),%rcx
mov %rax,(%rcx)
mov 0x50(%rsp),%rcx
mov %rdx,(%rcx)
mov $0x1,%rax
Done:
ret
三、编辑Makefile文件
ch02_05_0102:ch02_05_01.c ch02_05_02.o
gcc -g ch02_05_01.c ch02_05_02.o -o ch02_05_0102
ch02_05_02.o:ch02_05_02.asm
as ch02_05_02.asm -o ch02_05_02.o
四、编译、反汇编、gdb调试
编译后程序运行产生错误答案。利用反汇编可以查看完整的汇编程序。
$touch ch02_05_dump 创建ch02_05_dump空白文件
$objdump -d ./ch02_05_0102 >> ch02_05_dump 反汇编,并将反汇编的汇编程序传送到ch02_05_dump文件内。
查看反汇编文件,主要内容如下:
1、C语言IntegerMul函数代码:
401122: 55 push %rbp
401123: 48 89 e5 mov %rsp,%rbp
401126: 48 83 ec 30 sub $0x30,%rsp
40112a: c6 45 ff 02 movb $0x2,-0x1(%rbp)
40112e: 66 c7 45 fc fd ff movw $0xfffd,-0x4(%rbp)
401134: c7 45 f8 08 00 00 00 movl $0x8,-0x8(%rbp)
40113b: 48 c7 45 f0 04 00 00 movq $0x4,-0x10(%rbp)
401142: 00
401143: c6 45 ef 03 movb $0x3,-0x11(%rbp)
401147: 66 c7 45 ec f9 ff movw $0xfff9,-0x14(%rbp)
40114d: c7 45 e8 fb ff ff ff movl $0xfffffffb,-0x18(%rbp)
401154: 48 c7 45 e0 0a 00 00 movq $0xa,-0x20(%rbp)
40115b: 00
40115c: 0f bf 75 ec movswl -0x14(%rbp),%esi
401160: 44 0f be 4d ef movsbl -0x11(%rbp),%r9d
401165: 0f bf 55 fc movswl -0x4(%rbp),%edx
401169: 0f be 45 ff movsbl -0x1(%rbp),%eax
40116d: 4c 8b 45 f0 mov -0x10(%rbp),%r8
401171: 8b 4d f8 mov -0x8(%rbp),%ecx
401174: 48 83 ec 08 sub $0x8,%rsp
401178: ff 75 e0 pushq -0x20(%rbp)
40117b: 8b 7d e8 mov -0x18(%rbp),%edi
40117e: 57 push %rdi
40117f: 56 push %rsi
401180: 89 c6 mov %eax,%esi
401182: 48 8d 3d 7f 0e 00 00 lea 0xe7f(%rip),%rdi # 402008 <_IO_stdin_used+0x8>
401189: b8 00 00 00 00 mov $0x0,%eax
40118e: e8 9d fe ff ff callq 401030 <printf@plt>
401193: 48 83 c4 20 add $0x20,%rsp
401197: 0f be 55 ff movsbl -0x1(%rbp),%edx
40119b: 0f bf 45 fc movswl -0x4(%rbp),%eax
40119f: 0f af c2 imul %edx,%eax
4011a2: 0f af 45 f8 imul -0x8(%rbp),%eax
4011a6: 48 98 cltq
4011a8: 48 0f af 45 f0 imul -0x10(%rbp),%rax
4011ad: 48 89 c2 mov %rax,%rdx
4011b0: 48 0f be 45 ef movsbq -0x11(%rbp),%rax
4011b5: 48 0f af d0 imul %rax,%rdx
4011b9: 48 0f bf 45 ec movswq -0x14(%rbp),%rax
4011be: 48 0f af d0 imul %rax,%rdx
4011c2: 8b 45 e8 mov -0x18(%rbp),%eax
4011c5: 48 98 cltq
4011c7: 48 0f af c2 imul %rdx,%rax
4011cb: 48 8b 55 e0 mov -0x20(%rbp),%rdx
4011cf: 48 0f af c2 imul %rdx,%rax
4011d3: 48 89 45 d8 mov %rax,-0x28(%rbp)
4011d7: 44 0f bf 4d ec movswl -0x14(%rbp),%r9d
4011dc: 44 0f be 45 ef movsbl -0x11(%rbp),%r8d
4011e1: 0f bf 75 fc movswl -0x4(%rbp),%esi
4011e5: 0f be 45 ff movsbl -0x1(%rbp),%eax
4011e9: 48 8b 4d f0 mov -0x10(%rbp),%rcx
4011ed: 8b 55 f8 mov -0x8(%rbp),%edx
4011f0: ff 75 e0 pushq -0x20(%rbp)
4011f3: 8b 7d e8 mov -0x18(%rbp),%edi
4011f6: 57 push %rdi
4011f7: 89 c7 mov %eax,%edi
4011f9: e8 c4 01 00 00 callq 4013c2 <IntegerMul_>
4011fe: 48 83 c4 10 add $0x10,%rsp
401202: 48 89 45 d0 mov %rax,-0x30(%rbp)
401206: 48 8b 55 d0 mov -0x30(%rbp),%rdx
40120a: 48 8b 45 d8 mov -0x28(%rbp),%rax
40120e: 48 89 c6 mov %rax,%rsi
401211: 48 8d 3d 3b 0e 00 00 lea 0xe3b(%rip),%rdi # 402053 <_IO_stdin_used+0x53>
401218: b8 00 00 00 00 mov $0x0,%eax
40121d: e8 0e fe ff ff callq 401030 <printf@plt>
401222: 90 nop
401223: c9 leaveq
401224: c3 retq
2、C语言UnsignedIntegerDiv函数代码如下:
401225: 55 push %rbp
401226: 48 89 e5 mov %rsp,%rbp
401229: 48 83 ec 50 sub $0x50,%rsp
40122d: c6 45 ff 0c movb $0xc,-0x1(%rbp)
401231: 66 c7 45 fc 11 00 movw $0x11,-0x4(%rbp)
401237: c7 45 f8 c0 5f 3b 04 movl $0x43b5fc0,-0x8(%rbp)
40123e: 48 b8 00 04 6b f4 14 movabs $0x14f46b0400,%rax
401245: 00 00 00
401248: 48 89 45 f0 mov %rax,-0x10(%rbp)
40124c: c6 45 ef 65 movb $0x65,-0x11(%rbp)
401250: 66 c7 45 ec 25 00 movw $0x25,-0x14(%rbp)
401256: c7 45 e8 19 00 00 00 movl $0x19,-0x18(%rbp)
40125d: 48 c7 45 e0 05 00 00 movq $0x5,-0x20(%rbp)
401264: 00
401265: 0f b7 75 ec movzwl -0x14(%rbp),%esi
401269: 44 0f b6 4d ef movzbl -0x11(%rbp),%r9d
40126e: 0f b7 55 fc movzwl -0x4(%rbp),%edx
401272: 0f b6 45 ff movzbl -0x1(%rbp),%eax
401276: 4c 8b 45 f0 mov -0x10(%rbp),%r8
40127a: 8b 4d f8 mov -0x8(%rbp),%ecx
40127d: 48 83 ec 08 sub $0x8,%rsp
401281: ff 75 e0 pushq -0x20(%rbp)
401284: 8b 7d e8 mov -0x18(%rbp),%edi
401287: 57 push %rdi
401288: 56 push %rsi
401289: 89 c6 mov %eax,%esi
40128b: 48 8d 3d de 0d 00 00 lea 0xdde(%rip),%rdi # 402070 <_IO_stdin_used+0x70>
401292: b8 00 00 00 00 mov $0x0,%eax
401297: e8 94 fd ff ff callq 401030 <printf@plt>
40129c: 48 83 c4 20 add $0x20,%rsp
4012a0: 0f b6 55 ff movzbl -0x1(%rbp),%edx
4012a4: 0f b7 45 fc movzwl -0x4(%rbp),%eax
4012a8: 01 d0 add %edx,%eax
4012aa: 89 c2 mov %eax,%edx
4012ac: 8b 45 f8 mov -0x8(%rbp),%eax
4012af: 01 d0 add %edx,%eax
4012b1: 89 c2 mov %eax,%edx
4012b3: 48 8b 45 f0 mov -0x10(%rbp),%rax
4012b7: 48 01 d0 add %rdx,%rax
4012ba: 0f b6 4d ef movzbl -0x11(%rbp),%ecx
4012be: 0f b7 55 ec movzwl -0x14(%rbp),%edx
4012c2: 01 ca add %ecx,%edx
4012c4: 89 d1 mov %edx,%ecx
4012c6: 8b 55 e8 mov -0x18(%rbp),%edx
4012c9: 01 ca add %ecx,%edx
4012cb: 89 d1 mov %edx,%ecx
4012cd: 48 8b 55 e0 mov -0x20(%rbp),%rdx
4012d1: 48 8d 34 0a lea (%rdx,%rcx,1),%rsi
4012d5: ba 00 00 00 00 mov $0x0,%edx
4012da: 48 f7 f6 div %rsi
4012dd: 48 89 45 d8 mov %rax,-0x28(%rbp)
4012e1: 0f b6 55 ff movzbl -0x1(%rbp),%edx
4012e5: 0f b7 45 fc movzwl -0x4(%rbp),%eax
4012e9: 01 d0 add %edx,%eax
4012eb: 89 c2 mov %eax,%edx
4012ed: 8b 45 f8 mov -0x8(%rbp),%eax
4012f0: 01 d0 add %edx,%eax
4012f2: 89 c2 mov %eax,%edx
4012f4: 48 8b 45 f0 mov -0x10(%rbp),%rax
4012f8: 48 01 d0 add %rdx,%rax
4012fb: 0f b6 4d ef movzbl -0x11(%rbp),%ecx
4012ff: 0f b7 55 ec movzwl -0x14(%rbp),%edx
401303: 01 ca add %ecx,%edx
401305: 89 d1 mov %edx,%ecx
401307: 8b 55 e8 mov -0x18(%rbp),%edx
40130a: 01 ca add %ecx,%edx
40130c: 89 d1 mov %edx,%ecx
40130e: 48 8b 55 e0 mov -0x20(%rbp),%rdx
401312: 48 01 d1 add %rdx,%rcx
401315: ba 00 00 00 00 mov $0x0,%edx
40131a: 48 f7 f1 div %rcx
40131d: 48 89 55 d0 mov %rdx,-0x30(%rbp)
401321: 48 8b 55 d0 mov -0x30(%rbp),%rdx
401325: 48 8b 45 d8 mov -0x28(%rbp),%rax
401329: 48 89 c6 mov %rax,%rsi
40132c: 48 8d 3d 8e 0d 00 00 lea 0xd8e(%rip),%rdi # 4020c1 <_IO_stdin_used+0xc1>
401333: b8 00 00 00 00 mov $0x0,%eax
401338: e8 f3 fc ff ff callq 401030 <printf@plt>
40133d: 44 0f b7 4d ec movzwl -0x14(%rbp),%r9d
401342: 44 0f b6 45 ef movzbl -0x11(%rbp),%r8d
401347: 0f b7 75 fc movzwl -0x4(%rbp),%esi
40134b: 0f b6 45 ff movzbl -0x1(%rbp),%eax
40134f: 48 8b 4d f0 mov -0x10(%rbp),%rcx
401353: 8b 55 f8 mov -0x8(%rbp),%edx
401356: 48 8d 7d b8 lea -0x48(%rbp),%rdi
40135a: 57 push %rdi
40135b: 48 8d 7d c0 lea -0x40(%rbp),%rdi
40135f: 57 push %rdi
401360: ff 75 e0 pushq -0x20(%rbp)
401363: 8b 7d e8 mov -0x18(%rbp),%edi
401366: 57 push %rdi
401367: 89 c7 mov %eax,%edi
401369: e8 92 00 00 00 callq 401400 <UnsignedDiv_>
40136e: 48 83 c4 20 add $0x20,%rsp
401372: 89 45 cc mov %eax,-0x34(%rbp)
401375: 83 7d cc 00 cmpl $0x0,-0x34(%rbp)
401379: 75 13 jne 40138e <UnsignedIntegerDiv+0x169>
40137b: 48 8d 3d 54 0d 00 00 lea 0xd54(%rip),%rdi # 4020d6 <_IO_stdin_used+0xd6>
401382: b8 00 00 00 00 mov $0x0,%eax
401387: e8 a4 fc ff ff callq 401030 <printf@plt>
40138c: eb 1c jmp 4013aa <UnsignedIntegerDiv+0x185>
40138e: 48 8b 55 b8 mov -0x48(%rbp),%rdx
401392: 48 8b 45 c0 mov -0x40(%rbp),%rax
401396: 48 89 c6 mov %rax,%rsi
401399: 48 8d 3d 50 0d 00 00 lea 0xd50(%rip),%rdi # 4020f0 <_IO_stdin_used+0xf0>
4013a0: b8 00 00 00 00 mov $0x0,%eax
4013a5: e8 86 fc ff ff callq 401030 <printf@plt>
4013aa: 90 nop
4013ab: c9 leaveq
4013ac: c3 retq
3、分析代码:
(1)IntegerMul函数中40112a-401154,UnsignedIntegerDiv函数中40112d-40125d的代码说明两个函数都把a-h变量的值分别传递给-0x1(%rbp)、-0x4(%rbp)、-0x8(%rbp)、-0x10(%rbp)、-0x11(%rbp)、-0x14(%rbp)、-0x18(%rbp)、-0x20(%rbp)指向的内存空间内。
(2)用gdb查看各内存空间的值。
$gdb ./ch02_05_0102
(gdb)break IntegerMul 在IntegerMul函数处打断
(gdb)run 运行程序,到IntegerMul函数入口处中断
(gdb)display /d *(char *)($rbp-0x1) 显示第1个变量。/d表示显示十进制数。*(char *)表示按字节长度显示内存地址内的值,($rbp-0x1)表示寄存器rbp偏移-0x1的内存位置。注意gdb中寄存器前缀与汇编语言不同,gdb中寄存器前缀用$表示,汇编语言中用%表示。
(gdb)display /d *(short *)($rbp-0x4) 显示第2个变量,short表示按字的长度
(gdb)display /d *(int *)($rbp-0x8) 显示第3个变量,int表示按双字的长度
(gdb)display /d *(long *)($rbp-0x10) 显示第4个变量,long表示按四字的长度。第5-8个变量按类似方式操作。
(gdb)si 执行下一步,随着一步步调试执行,可以观察内存值的变化。
(3)汇编函数UnsignedDiv_还要传递商值和余数值到C语言中,在C语言反汇编UnsignedIntegerDiv代码第401356-40135b中
401356: 48 8d 7d b8 lea -0x48(%rbp),%rdi
40135a: 57 push %rdi
40135b: 48 8d 7d c0 lea -0x40(%rbp),%rdi
可知商值和余数值分别传递到-0x40(%rbp)、-0x48(%rbp)空间内。lea指令表示传递有效地址。
四、修改汇编程序
根据上述分析,修改汇编程序如下:
.text
.global IntegerMul_ /*定义用于有符号乘法计算的函数*/
.global UnsignedDiv_ /*定义用于无符号除法计算的函数*/
IntegerMul_:
movsbq -0x1(%rbp),%rdi /*movsbq指令表示将8位字节按有符号扩展到64位四字,其中dil是rdi低8位寄存器*/
movswq -0x4(%rbp),%rsi /*movswq指令表示将16位字按有符号扩展到64位四字,其中si是rsi低16位寄存器*/
imulq %rsi,%rdi /*rdi=a*b*/
movq %rdi,%rax /*rax=a*b */
movslq -0x8(%rbp),%rdx /*movslq指令表示将32位双字按有符号扩展到64位四字*/
imulq -0x10(%rbp),%rdx /*rdx=c*d*/
imulq %rdx,%rax /*rax=a*b*c*d*/
movsbq -0x11(%rbp),%r8 /*r8=e*/
movswq -0x14(%rbp),%r9 /*r9=f*/
imulq %r9,%r8 /*r8=e*f */
imulq %r8,%rax /*rax=a*b*c*d*e*f */
movslq -0x18(%rbp),%rdx /*rdx=g*/
imulq -0x20(%rbp),%rdx /*rdx=g*h*/
imulq %rdx,%rax /*rax=a*b*c*d*e*f*g*h */
ret
UnsignedDiv_:
addq %rsi,%rdi /*rdi=a+b */
addq %rdx,%rdi /*rdi=a+b+c */
addq %rcx,%rdi /*rdi=a+b+c+d */
movq %rdi,%rax /*rax=a+b+c+d */
xor %rdx,%rdx /*被除数为rdx:rax,将高位的rdx清零*/
addq %r9,%r8 /*r8=e+f */
mov -0x18(%rbp),%edi /*edi=g*/
mov %edi,%edi /*将edi扩展为64位*/
addq %rdi,%r8 /*r8=e+f+g */
mov -0x20(%rbp),%edi
mov %edi,%edi
addq %rdi,%r8 /*r8=e+f+g+h */
jnz DivOK /*当被除数r8不为0时,除法计算有效,跳转到DivOK执行除法计算,否则计算无效*/
xor %rax,%rax /*rax清零,除法计算无效时返回值为0*/
jmp Done
DivOK:
divq %r8 /*rdx:rax/r8,商保存在rax,余数保存在rdx*/
movq %rax,-0x40(%rbp) /*商传递到-0x40(%rbp)地址内,该地址传递给变量quo2*/
movq %rdx,-0x48(%rbp) /*余数传递到-0x48(%rbp)地址内,该地址传递给变量rem2*/
movq $1,%rax /*除法计算有效时,返回值为1*/
Done:
ret
最后经编译运行结果正确,运行结果如下:
Results for IntegerMul
a=2 b=-3 c=8 d=4 e=3 f=-7 g=-5 h=10
prod1=-201600
prod2=-201600
Results for UnsignedIntegerDiv
a=12 b=17 c=71000000 d=90000000000 e=101 f=37 g=25 h=5
quo1=536136904 ,rem1=157
quo2=536136904, rem2=157
标签: #c语言和e语言