汇编之有趣的计算机
Wirte by 021. Leave a message if i messed up ! : )
汇编的加减乘除:
1 2 3 4 5 6 7 8 9 10 11
| 汇编语言 编译器 机器语言
加 INC EAX ---> 0100 0000
减 DEC EAX ---> 0100 1000
乘 MUL EAX ---> 1111 0111 1110 0000
除 DIV EAX ---> 1111 0111 1111 0000
|
进制换算
1 2 3 4 5 6 7 8 9 10 11 12
| 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 2 3 4 5 6 7 8 9 A B C D E F
测试: hex : 6d 7f 008c e3 246
hex to bin 6 + d = 0110 1101, 7 + f = 0111 1111, 8 + c =0000 0000 1000 1100, e + 3 = 1110 0011, 2 + 4 + 6 = 0010 0100 0110.
|
数据宽度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 位 bit: 0,最大值 1.
字节 byte: 0000 0000 , 最大值 1111 1111 , 0 - ff. 0xff.
字word: 0000 0000 0000 0000 ,最大值 1111 1111 1111 1111 , 0 - ffff, 0xffff.
双字doubleWord: 0000 0000 0000 0000 0000 0000 0000 0000 0000 , 最大值 0xffffffff.
数据宽度测试: char a = 0x1ff, 存入数据是ff 舍弃了1,因为宽度不够.
Xcode 进入debug 模式, 在右边控制台或者内存值, 输出:
x/1xb 0x7ffeefbff3df , 取1个字节的值,用16进制表示,表示单字节 0x7ffeefbff3df: 0xff 只存了ff。
x/nfu <addr>
n,表示要显示的内存单元的个数 f,表示显示方式, 可取如下值: x 按十六进制格式显示变量 d 按十进制格式显示变量 u 按十进制格式显示无符号整型 o 按八进制格式显示变量 t 按二进制格式显示变量 a 按十六进制格式显示变量 i 指令地址格式 c 按字符格式显示变量 f 按浮点数格式显示变量
u,表示一个地址单元的长度: b 表示单字节 h 表示双字节 w 表示四字节 g 表示八字节
x/16xb self 会显示 self 指针地址内容,16 个字节,16 进制。 x/8cb 0x7fc359a03040 会显示地址 0x7fc359a03040 地址的内容,8 个字节,按字符格式显示。
|
有符号 与 无符号
1
| 无符号 0000 0001 就是 0000 0001,
|
1 2 3 4 5 6 7 8 9 10 11 12
| 测试: 1 , 0x01, 最高位 0, 是正数. 0000 0001
最高位 1,是负数. 1000 0001 , 0x81
int x = 0x81000000; printf("有符号表示 %u\n",x); printf("无符号表示 %d\n",x); 有符号表示 2164260864 无符号表示 -2130706432
|
原码 反码 补码
原码
1 2
| 最高位是符号位,其余位为数值的绝对值. 1 的原码 0000 0001
|
反码
1 2 3
| -1 原码: 1000 0001 反码: 1111 1110 , 最高位不变.
|
补码 -!!!负数存储!!!
位运算
与运算
- **同位为1,结果才是1,否则是0. **
- 并且(当2个开关都闭合灯才亮)
1 2 3 4
| 测试:C: 1 & 2 , assembly: and 0000 0001 0000 0010 结果 : 0000 0000; 结果为0;
|
或运算
- 同位只要有1,就是1
- 或者 (两个开关只要一个开关闭合灯就能亮)
1 2 3 4 5
| 测试: C: 1 | 2 , assembly : or 0000 0001 0000 0010 结果为: 0000 0011; 结果为3;
|
异或运算
1 2 3 4 5 6
| 测试: C: 1 ^ 2 , assembly : xor 0000 0001 0000 0010 结果为: 0000 0011; 结果为3;
|
非运算
1 2 3 4 5
| 测试: 1 ,C: ~ , assembly : not 0000 0001
结果为: 1111 1110;
|
左移运算
1 2 3 4 5 6 7 8 9 10
| C:<< , assembly : shl
测试 : 1,左移1位, 0000 0001 ,结果: 0000 0010; = 2. 左移2; 0000 0001, 结果: 0000 0100; = 4.
char c = 1 << 2; 输出为:4
|
右移运算
- 各二进制位向右移动若干位,无符号高位补0或者有符号高位补1,低位丢弃
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| C:>> , assembly : shr
测试 : 1,
右移1位, 0000 0001 ,结果: 0000 0000; = 0. 右移2; 0000 0001, 结果: 0000 0000; = 0.
补符号: 高位补1 C:>> , assembly : sar 测试数: 10;右移2位; 0000 1100; 结果: 1000 0011; 负数存的是反码+1, 1111 1101, 内存值= 0xfd;
1000 1010 -> 1111 0110 补码值 :0xf6 右移-> 1111 1101; fd
|
+ - * /
+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| 求 10 + 7 = ? //混搭伪代码 int a = 10; int b = 7;
funcAdd(a,b) { //转换 0000 1010 0000 0111 //第一步先异或 int tmp = funXor(a,b) funXor(a,b); = 0000 1101 //第二步判断是否有进位 int shlTemp = funcCmp(a,b); 0000 0010; 有进位 //判断是否有进位 , if(shlTemp!=0) { //有进位需要位移,位移后的值. int shlTempValue = funcSHL(shlTemp,1); 0000 0100; //将第一次的结果与进位的结果异或 ,第一次递归调用 funcAdd(tmp,shlTempValue); //第二次异或; 0000 1101 0000 0100 = tmp = 0000 1001; 第二次与运算对比,有进位;shlTemp = 0000 0100 shlTempValue = funcSHL(shlTemp ,1) = 0000 1000; //第二次递归调用funcAdd(tmp, shlTempValue); 0000 1001 0000 1000 //第三次异或运算 tem = 0000 0001 //第三次对比 与 运算 shlTemp =0000 1000; //有进位,第三次位移 shlTempValue = 0001 0000; //第三次次递归调用funcAdd(tmp, shlTempValue) //第四次异或 0000 0001 0001 0000 tem = 0001 0001 = 17; //第四次与运算,判断是否有进位 //第四次无进位,判断执行完毕,执行后面代码 } returun tem;
}
//与运算 funcCmp(a,b) { 0000 1010 & 0000 0111 return a&b = 0000 0010; 如果非0,作为返回值继续异或 }
//左移1位 funcSHL(int a,int offset){ a = 0000 0010; offset = 1; return a << 1 = 0000 0100; }
//异或运算 funXor(a,b) { a = 0000 1010 b = 0000 0111 // 假设没进位 return a^b; 0000 1101; }
|
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| 求 10 - 7 = ?
减法就是加法 , 10-7 = 1 + (-7); -7 是补码存储,求补码: 正码: 0000 0111; 反码: 1111 1000;补码=反码+1= 1111 1001; 内存=0xf9;
//混搭伪代码 int a = 10; int b = -7; funcAdd(a,b) { //转换 0000 1010 1111 1001 //第一步先异或 int tmp = funXor(a,b) funXor(a,b); = 1111 0011 //第二步判断是否有进位 int shlTemp = funcCmp(a,b); 0000 1000; 有进位 //判断是否有进位 , if(shlTemp!=0) { //有进位需要位移,位移后的值. int shlTempValue = funcSHL(shlTemp,1); 0001 0000; //将第一次的结果与进位的结果异或 ,第一次递归调用 funcAdd(tmp,shlTempValue); //第二次异或; 1111 0011 0001 0000 = tmp = 1110 0011; 第二次与运算对比,有进位;shlTemp = 0001 0000 shlTempValue = funcSHL(shlTemp ,1) = 0010 0000; --------------n次递归----------------- 求 10 - 7 = 10 + (-7) 0000 1010 1111 1001 异或 tmp = 1111 0011 进位: 0000 1000 进位后的值 shlTempValue = funcSHL(000 1000 ,1) = 0001 0000 ------------------------------------- 1111 0011 0001 0000 异或 tmp = 1110 0011 进位: 0001 0000 进位后的值 shlTempValue = funcSHL(0001 0000 ,1) = 0010 0000 --------------------------------------- 1110 0011 0010 0000 tmp = 1100 0011 shlTempValue = funcSHL(0010 0000 ,1) = 0100 0000 ------------------------------- 0100 0000 1100 0011 tmp = 1000 0011 shlTempValue = funcSHL(0100 0000 ,1) = 1000 0000 --------------------------------- 1000 0000 1000 0011 tmp = 1000 0011; shlTempValue = funcSHL(0100 0000 ,1) = 0001 0000 0000 0001 0000 0000 0000 0000 0011 0001 0000 0011 ??????WTF 此时结果产生了溢出; 篇幅原因 就不展开讲了 ------------------------------------- tem = 0001 0000 0011 ; //第四次与运算,判断是否有进位 //第四次无进位,判断执行完毕,执行后面代码 } returun tem;
}
//与运算 funcCmp(a,b) { 0000 1010 & 0000 0111 return a&b = 0000 0010; 如果非0,作为返回值继续异或 }
//左移1位 funcSHL(int a,int offset){ a = 0000 0010; offset = 1; return a << 1 = 0000 0100; }
//异或运算 funXor(a,b) { a = 0000 1010 b = 0000 0111 // 假设没进位 return a^b; 0000 1101; }
|
*
1 2 3 4 5 6 7 8 9
| 求 10 * 7 = ? 解: 7 个 10 相加; int a = 10; int b = 7;
for (int i =0; i < 7 ; i++ ){ funcAdd(a,a); }
|
/
1 2 3 4 5 6 7 8 9 10
| 求 10 * 7 = ? 解: 7 个 10 相加; int a = 10; int b = 7;
for (int i =0; i < 7 ; i++ ){ //转换补码负数 b = 1111 1001; funcAdd(a,b); }
|