概述
語言
電子計算機:只有0和1兩個狀態
機器語言:由0和1組成
假設:
加 0001 0110
減 0100 1000
乘 1101 0111
除 0100 0011
匯編語言:為了助計機器語言,用inc表示加,然后通過編譯器轉換為機器語言
加 INC -> 編譯器 0001 0110
減 DEC-> 編譯器 0100 1000
乘 MUL-> 編譯器 1101 0111
除 DIV-> 編譯器 0100 0011
C語言:更加簡化機器語言,便於學習和記憶
加 A+B -> 編譯器 0001 0110
減 A-B -> 編譯器 0100 1000
乘 A*B -> 編譯器 1101 0111
除 A/B -> 編譯器 0100 0011
進制
一進制: 1 11 111 1111 11111 111111 1111111 11111111 111111111
二進制: 0 1 10 11 100 101 110 111 1000
八進制:0 1 2 3 4 5 6 7 10 11 12
十進制:0 1 2 3 4 5 6 7 8 9 10
十六進制:0 1 2 3 4 5 6 7 8 9 a b c d e f
進制運算
進制運算的本質就是查數
使用8進制計算下面的運算
277+333
277*54
277-35
234/4
277
333 +
--------
632
===============
277
54 *
--------
1374
1673 +
--------
20324
===============
277
35 -
--------
242
===============
234
4 /
--------
47(查看乘法表,看哪個數與4相乘與23接近)
結論:無論是什么進制,本身都有一套完美的運算體系,都可以通過列表的形式將其計算出。
二進制
二進制 0 ~ 1111
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
二進制這樣寫很麻煩,為了簡化,使用十六進制
0 1 2 3 4 5 6 7 8 9 a b c d e f
1111 1111 :使用16進制表示 0xFF
數據寬度
在計算機中,需要給數據增加計算寬度。因為內存是有限的
強類型語言中,都需要給數據定義類型,String int ...
位 0 1
字節 0~0xFF
字 0~0xFFFF
雙字 0~0xFFFFFFFF
==在計算機中,都需要給數據定義類型,在內存中給它定義寬度==
有符號數和無符號數
數據都是有寬度的,但是給你一個二進制數字,你怎么知道它代表什么含義?
規則,給二進制解碼增加一個規則
無符號數規則
這個數是什么,就是什么
1001 1010
轉換為十六進制: 0x9A
十進制:154
有符號數規則
最高位是符號位,1(負數) 0(正數)
負數在計算機中是以補碼的形式存在的
已知該二進制表示的是一個負數,求其十進制表示的數
1001 1010
--------------
1.該二進制是一個補碼,先求其原碼的反碼,即補碼減1
反碼 1001 1001
原碼 1110 0110
轉換為十進制就是 -102
原碼反碼補碼
編碼規則
有符號數編碼規則
原碼:最高位符號位,對其他的進行本身絕對值即可
反碼
- 正數:反碼和原碼相同
- 負數符號位是1,其他位對原碼取反
補碼
- 正數:反碼和原碼相同
- 負數符號位是1,反碼+1
測試,都是按照8位來運算的
求1的原碼反碼補碼
1 如果是正數,都是一樣的
原碼 0000 0001
反碼 0000 0001
補碼 0000 0001
--------------------
求-1的原碼反碼補碼
-1 如果是負數
原碼 1000 0001
反碼 1111 1110
補碼 1111 1111
--------------------
求-7的原碼反碼補碼
-7
原碼 1000 0111
反碼 1111 1000
補碼 1111 1001
如果看到一個二進制數,需要了解是有符號數還是無符號數
二進制的標志:
2 10
4 100
8 1000
16 10000
寄存器:用來存值,速度比內存快
命令: mov 哪個寄存器,值
-1在32位寄存器中的表示是0xFFFFFFFF
用二進制表示就是1111 1111 1111 1111 1111 1111 1111 1111
結論:負數在寄存器中是以補碼的形式存放的
位運算
學習位運算需要掌握原碼反碼補碼
2*8最高效計算方式:通過位運算(左移一位就是乘以2)
public class test {
public static void main(String[] args) {
int a = 8;
System.out.println(a<<1); //16
}
}
很多底層的調試器,需要通過位來判斷CPU的狀態
與運算(and &)
計算機的本質
與運算:兩個都為1,結果為1,任意有一個為0,結果都是0
1001 0110
1010 1100
----------
1000 0100
或運算(or |)
或運算:一個為1,結果就是1
1001 0110
1010 1100
----------
1011 1110
異或運算(xor ^)
不一樣就是1
異或運算:不相同就是1,相同就是0
1001 0110
1010 1100
----------
0011 1010
非運算符(單目運算符 not ~)
非運算:對其取反
1001 0110
----------
0110 1001
通過這些位運算可以完成加減乘除
位運算
左移乘2,右移除2 (對於十進制來說)
高位就是左邊,低位就是右邊
左移(shl <<)
0000 0110 所有二進制位全部左移若干位,高位丟棄,低位補0
左移一位:0000 1100
右移(shr >>)
1000 0110 所有二進制位全部右移若干位,低位丟棄,低位補0,1(根據符號)
右移一位:1000 0011
位運算(移動位)
左移: 十進制
0000 0001 1
0000 0010 2
0000 0100 4
0000 1000 8
位運算計算
計算機只認識0和1,基本數學是建立在加減乘除上面的(核心是加法)
4+5?
計算機是怎么操作4+5的
0000 0100
0000 0101
----------
0000 1001 (加法,計算機是不會直接加的,計算機只懂,與或非,異或)
計算機實現原理
第一步,異或,(如果不考慮進位,異或可以直接出結果)
0000 0100
0000 0101
----------異或(不相同為1)
0000 0001
第二步,與運算(判斷進位,如果與運算結果為0,說明沒有進位)
0000 0100
0000 0101
----------與運算(同為1,結果為1)
0000 0100
第三步,將與運算的結果左移一位(因為進位,需要左移)
0000 0100
----------左移一位
0000 1000
第四步,異或運算(第一次異或結果與左移后的結果進行異或運算)
0000 0001
0000 1000
----------異或運算
0000 1001
第五步,與運算(判斷進位是否為0)
0000 0001
0000 1000
----------與運算
0000 0000
結果為0,證明沒有進位,所以最終結果是0000 1001
4-5?
計算機是沒有減法的 4+(-5)
負數在寄存器中是以補碼的形式存放的
5
0000 0101
原碼 1000 0101
反碼 1111 1010
補碼 1111 1011
所以-5 就是1111 1011
------------------
4+(-5)
0000 0100
1111 1011
----------結果也是一個二進制的補碼,根據補碼求原碼就能知道該數
1111 1111
----------
補碼 1111 1111
反碼 1111 1110
原碼 1000 0001
最高位為1表示負數,所以結果是-1
----------------------------------------------
計算機實現原理
第一步,異或
0000 0100
1111 1011
----------異或(不相同為1)
1111 1111
第二步,與運算(判斷進位,如果與運算結果為0,說明沒有進位)
0000 0100
1111 1011
----------與運算(同為1,結果為1)
0000 0000
結果為0,證明沒有進位,所以最終結果是1111 1111
再根據補碼求原碼即可。
乘法:x*y (本質是y個x相加)
除法:x/y (本質上減法,看x能減去多少個y)
符號位在計算機中很重要
0xFF
有符號位:-1
無符號位:255
匯編
通用寄存器
寄存器:
存儲數據:CPU>內存>硬盤
32位CPU
64位CPU
通用寄存器:可以存儲任意的東西
32位的通用寄存器只有8個
EAX ECX EDX EBX
ESP EBP ESI EDI
寄存器存值的范圍 0~0xFFFFFFFF
對於二進制來說,直接修改值
計算機如何向寄存器中存值
匯編:mov指令
mov 存的地址,存的數
mov 存的地址1,存的地址2
可以將數字寫入到寄存器中,也可以將寄存器中的值寫到寄存器
不同的寄存器
32位 16位 8位(分為高8位和低8位)
0xFFFFFFFF 0xFFFF 0xFF
EAX AX AL
ECX CX CL
EDX DX DL
EBX BX BL
ESP SP AH
EBP BP CH
ESI SI DH
EDI DI BH
L:低8位,H:高8位
向高8位存1 00000100
向低8位存1 00000001
所以:高8位加低8位也是一個16位的狀態
mov cl,01 -- 00000001
mov ch,01 -- 00000101
除了通用寄存器,還有其他的寄存器,每一位都有獨特的功能。
內存
內存地址
存一個數:占用的大小,數據寬度
計算機中內存地址很多,空間很大,每個空間都有一個地址
給內存起的編號,就是內存地址 0x0011FF11
范圍0x00000000~0xFFFFFFFF
32位的尋址能力只有4GB
一共有多少個內存空間0xFFFFFFFF+1 就是1 0000 0000,轉換為十進制就是42 9496 7296
/1024=4194304KB/1024=4096MB/1024=4GB
內存如何存值
需要知道:
數據寬度 :byte(8位) word(16位) dword(32位) qword(64位)
地址的位置:0xFFFFFFFF
不是任意的地址都能寫東西的,只能在申請的空間中寫數據
匯編向內存中存值
mov 數據寬度 內存地址,需要寫入的數
如: mov byte ptr ds:[0x0019FF70],0x1
傳遞的值得大小一定不能超過定義的數據寬度,不然無法寫入
內存地址有多種寫法
ds:[0x0019ff70+4](內存地址偏移)
ds:[eax](地址中也可以存放寄存器)
ds:[eax+4](寄存器偏移)
ds:[reg+reg{1,2,4,8}] (數組)
ds:[reg+reg{1,2,4,8}+4](數組偏移)