⑴ 匯編中eax,ecx,edx,ebx,esp,ebp,esi,edi,eip分別是什麼有什麼用
這些來是32位的CPU中32位的寄存器的名字自。
寄存器是CPU內部的用於運行中暫存數據的存儲單元。
在PC用的16位CPU 8086、8088中,寄存器的名字分別是AX(累加器),BX(基址寄存器),CX(計數寄存器),DX(數據寄存器),SP(堆棧指針),BP(基址指針),SI(源變址寄存器),DI(目的變址寄存器),IP(指令指針),等等……
這些寄存器除了從名字可以看得出來的用途以外,一部分寄存器也可以作為通用的一般數據寄存使用。具體每個寄存器的功能要與各種具體的指令關聯起來才能理解清楚。
在386以上的32位CPU中,這些寄存器擴展成了32位的,名字就是在原來16位的名字前面加一個字母E,變成了EAX,EBX,…………
⑵ X86指令集的內容有哪些
x86匯編指令集
數據傳輸指令 它們在存貯器和寄存器、寄存器和輸入輸出埠之間傳送數據.
1. 通用數據傳送指令.
MOV 傳送字或位元組.
MOVSX 先符號擴展,再傳送.
MOVZX 先零擴展,再傳送.
MOVSX reg16,r/m8 ; o16 0F BE /r [386]
MOVSX reg32,r/m8 ; o32 0F BE /r [386]
MOVSX reg32,r/m16 ; o32 0F BF /r [386]
MOVZX reg16,r/m8 ; o16 0F B6 /r [386]
MOVZX reg32,r/m8 ; o32 0F B6 /r [386]
MOVZX reg32,r/m16 ; o32 0F B7 /r [386]
PUSH 把字壓入堆棧.
POP 把字彈出堆棧.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次壓入堆棧.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次彈出堆棧.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次壓入堆棧.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次彈出堆棧.
BSWAP 交換32位寄存器里位元組的順序
XCHG 交換字或位元組.( 至少有一個操作數為寄存器,段寄存器不可作為操作數)
CMPXCHG 比較並交換操作數.( 第二個操作數必須為累加器AL/AX/EAX )
XADD 先交換再累加.( 結果在第一個操作數里 )
XLAT 位元組查表轉換.
—— BX 指向一張 256 位元組的表的起點, AL 為表的索引值 (0-255,即
0-FFH); 返回 AL 為查表結果. ( [BX+AL]->AL )
2. 輸入輸出埠傳送指令.
IN I/O埠輸入. ( 語法: IN 累加器, {埠號│DX} )
OUT I/O埠輸出. ( 語法: OUT {埠號│DX},累加器 )
輸入輸出埠由立即方式指定時, 其范圍是 0-255; 由寄存器 DX 指定時,
其范圍是 0-65535.
3. 目的地址傳送指令.
LEA 裝入有效地址.
例: LEA DX,string ;把偏移地址存到DX.
LDS 傳送目標指針,把指針內容裝入DS.
例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 傳送目標指針,把指針內容裝入ES.
例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 傳送目標指針,把指針內容裝入FS.
例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 傳送目標指針,把指針內容裝入GS.
例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 傳送目標指針,把指針內容裝入SS.
例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 標志傳送指令.
LAHF 標志寄存器傳送,把標志裝入AH.
SAHF 標志寄存器傳送,把AH內容裝入標志寄存器.
PUSHF 標志入棧.
POPF 標志出棧.
PUSHD 32位標志入棧.
POPD 32位標志出棧.
二、算術運算指令
———————————————————————————————————————
ADD 加法.
ADC 帶進位加法.
INC 加 1.
AAA 加法的ASCII碼調整.
DAA 加法的十進制調整.
SUB 減法.
SBB 帶借位減法.
DEC 減 1.
NEC 求反(以 0 減之).
CMP 比較.(兩操作數作減法,僅修改標志位,不回送結果).
AAS 減法的ASCII碼調整.
DAS 減法的十進制調整.
MUL 無符號乘法.
IMUL 整數乘法.
以上兩條,結果回送AH和AL(位元組運算),或DX和AX(字運算),
AAM 乘法的ASCII碼調整.
DIV 無符號除法.
IDIV 整數除法.
以上兩條,結果回送:
商回送AL,余數回送AH, (位元組運算);
或 商回送AX,余數回送DX, (字運算).
AAD 除法的ASCII碼調整.
CBW 位元組轉換為字. (把AL中位元組的符號擴展到AH中去)
CWD 字轉換為雙字. (把AX中的字的符號擴展到DX中去)
CWDE 字轉換為雙字. (把AX中的字元號擴展到EAX中去)
CDQ 雙字擴展. (把EAX中的字的符號擴展到EDX中去)
三、邏輯運算指令
———————————————————————————————————————
AND 與運算.
OR 或運算.
XOR 異或運算.
NOT 取反.
TEST 測試.(兩操作數作與運算,僅修改標志位,不回送結果).
SHL 邏輯左移.
SAL 算術左移.(=SHL)
SHR 邏輯右移.
SAR 算術右移.(=SHR)
ROL 循環左移.
ROR 循環右移.
RCL 通過進位的循環左移.
RCR 通過進位的循環右移.
以上八種移位指令,其移位次數可達255次.
移位一次時, 可直接用操作碼. 如 SHL AX,1.
移位>1次時, 則由寄存器CL給出移位次數.
如 MOV CL,04
SHL AX,CL
四、串指令
———————————————————————————————————————
DS:SI 源串段寄存器 :源串變址.
ES:DI 目標串段寄存器:目標串變址.
CX 重復次數計數器.
AL/AX 掃描值.
D標志 0表示重復操作中SI和DI應自動增量; 1表示應自動減量.
Z標志 用來控制掃描或比較操作的結束.
MOVS 串傳送.
( MOVSB 傳送字元. MOVSW 傳送字. MOVSD 傳送雙字. )
CMPS 串比較.
( CMPSB 比較字元. CMPSW 比較字. )
SCAS 串掃描.
把AL或AX的內容與目標串作比較,比較結果反映在標志位.
LODS 裝入串.
把源串中的元素(字或位元組)逐一裝入AL或AX中.
( LODSB 傳送字元. LODSW 傳送字. LODSD 傳送雙字. )
STOS 保存串.
是LODS的逆過程.
REP 當CX/ECX<>0時重復.
REPE/REPZ 當ZF=1或比較結果相等,且CX/ECX<>0時重復.
REPNE/REPNZ 當ZF=0或比較結果不相等,且CX/ECX<>0時重復.
REPC 當CF=1且CX/ECX<>0時重復.
REPNC 當CF=0且CX/ECX<>0時重復.
五、程序轉移指令
———————————————————————————————————————
1>無條件轉移指令 (長轉移)
JMP 無條件轉移指令
CALL 過程調用
RET/RETF過程返回.
2>條件轉移指令 (短轉移,-128到+127的距離內)
( 當且僅當(SF XOR OF)=1時,OP1 JA/JNBE 不小於或不等於時轉移.
JAE/JNB 大於或等於轉移.
JB/JNAE 小於轉移.
JBE/JNA 小於或等於轉移.
以上四條,測試無符號整數運算的結果(標志C和Z).
JG/JNLE 大於轉移.
JGE/JNL 大於或等於轉移.
JL/JNGE 小於轉移.
JLE/JNG 小於或等於轉移.
以上四條,測試帶符號整數運算的結果(標志S,O和Z).
JE/JZ 等於轉移.
JNE/JNZ 不等於時轉移.
JC 有進位時轉移.
JNC 無進位時轉移.
JNO 不溢出時轉移.
JNP/JPO 奇偶性為奇數時轉移.
JNS 符號位為 "0" 時轉移.
JO 溢出轉移.
JP/JPE 奇偶性為偶數時轉移.
JS 符號位為 "1" 時轉移.
3>循環控制指令(短轉移)
LOOP CX不為零時循環.
LOOPE/LOOPZ CX不為零且標志Z=1時循環.
LOOPNE/LOOPNZ CX不為零且標志Z=0時循環.
JCXZ CX為零時轉移.
JECXZ ECX為零時轉移.
4>中斷指令
INT 中斷指令
INTO 溢出中斷
IRET 中斷返回
5>處理器控制指令
HLT 處理器暫停, 直到出現中斷或復位信號才繼續.
WAIT 當晶元引線TEST為高電平時使CPU進入等待狀態.
ESC 轉換到外處理器.
LOCK 封鎖匯流排.
NOP 空操作.
STC 置進位標志位.
CLC 清進位標志位.
CMC 進位標志取反.
STD 置方向標志位.
CLD 清方向標志位.
STI 置中斷允許位.
CLI 清中斷允許位.
六、偽指令
———————————————————————————————————————
DW 定義字(2位元組).
PROC 定義過程.
ENDP 過程結束.
SEGMENT 定義段.
ASSUME 建立段寄存器定址.
ENDS 段結束.
END 程序結束.
七、寄存器
1. Register usage in 32 bit Windows
Function parameters are passed on the stack according to the calling conventions listed on
page 13. Parameters of 32 bits size or less use one DWORD of stack space. Parameters
bigger than 32 bits are stored in little-endian form, i.e. with the least significant DWORD at the
lowest address, and DWORD aligned.
Function return values are passed in registers in most cases. 8-bit integers are returned in
AL, 16-bit integers in AX, 32-bit integers, pointers, and Booleans in EAX, 64-bit integers in
EDX:EAX, and floating-point values in ST(0). Structures and class objects not exceeding
64 bits size are returned in the same way as integers, even if the structure contains floating
point values. Structures and class objects bigger than 64 bits are returned through a pointer
passed to the function as the first parameter and returned in EAX. Compilers that don\'t
support 64-bit integers may return structures bigger than 32 bits through a pointer. The
Borland compiler also returns structures through a pointer if the size is not a power of 2.
Registers EAX, ECX and EDX may be changed by a procere. All other general-purpose
registers (EBX, ESI, EDI, EBP) must be saved and restored if they are used. The value of
ESP must be divisible by 4 at all times, so don\'t push 16-bit data on the stack. Segment
registers cannot be changed, not even temporarily. CS, DS, ES, and SS all point to the flat
segment group. FS is used for a thread environment block. GS is unused, but reserved.
Flags may be changed by a procere with the following restrictions: The direction flag is 0
by default. The direction flag may be set temporarily, but must be cleared before any call or
return. The interrupt flag cannot be cleared. The floating-point register stack is empty at the
entry of a procere and must be empty at return, except for ST(0) if it is used for return
value. MMX registers may be changed by the procere and if so cleared by EMMS before
returning and before calling any other procere that may use floating-point registers. All
XMM registers can be modified by proceres. Rules for passing parameters and return
values in XMM registers are described in Intel\'s application note AP 589 "Software
Conventions for Streaming SIMD Extensions". A procere can rely on EBX, ESI, EDI, EBP
and all segment registers being unchanged across a call to another procere.
2. Register usage in Linux
The rules for register usage in Linux appear to be almost the same as for 32-bit windows.
Registers EAX, ECX, and EDX may be changed by a procere. All other general-purpose
registers must be saved. There appears to be no rule for the direction flag. Function return
values are transferred in the same way as under Windows. Calling conventions are the
same, except for the fact that no underscore is prefixed to public names. I have no
information about the use of FS and GS in Linux. It is not difficult to make an assembly
function that works under both Windows and Linux, if only you take these minor differences
into account.
八、位操作指令,處理器控制指令
1.位操作指令,8086新增的一組指令,包括位測試,位掃描。BT,BTC,BTR,BTS,BSF,BSR
1.1 BT(Bit Test),位測試指令,指令格式:
BT OPRD1,OPRD2,規則:操作作OPRD1可以是16位或32位的通用寄存器或者存儲單元。操作數OPRD2必須是8位立即數或者是與OPRD1操作數長度相等的通用寄存器。如果用OPRD2除以OPRD1,假設商存放在Divd中,余數存放在Mod中,那麼對OPRD1操作數要進行測試的位號就是Mod,它的主要功能就是把要測試位的值送往CF,看幾個簡單的例子:
1.2 BTC(Bit Test And Complement),測試並取反用法和規則與BT是一樣,但在功能有些不同,它不但將要測試位的值送往CF,並且還將該位取反。
1.3 BTR(Bit Test And Reset),測試並復位,用法和規則與BT是一樣,但在功能有些不同,它不但將要測試位的值送往CF,並且還將該位復位(即清0)。
1.4 BTS(Bit Test And Set),測試並置位,用法和規則與BT是一樣,但在功能有些不同,它不但將要測試位的值送往CF,並且還將該位置位(即置1)。
1.5 BSF(Bit Scan Forward),順向位掃描,指令格式:BSF OPRD1,OPRD2,功能:將從右向左(從最低位到最高位)對OPRD2操作數進行掃描,並將第一個為1的位號送給操作數OPRD1。操作數OPRD1,OPRD2可以是16位或32位通用寄存器或者存儲單元,但OPRD1和OPRD2操作數的長度必須相等。
1.6 BSR(Bit Scan Reverse),逆向位掃描,指令格式:BSR OPRD1,OPRD2,功能:將從左向右(從最高位到最低位)對OPRD2操作數進行掃描,並將第一個為1的位號送給操作數OPRD1。操作數OPRD1,OPRD2可以是16位或32位通用寄存器或存儲單元,但OPRD1和OPRD2操作數的長度必須相等。
1.7 舉個簡單的例子來說明這6條指令:
AA DW 1234H,5678H
BB DW 9999H,7777H
MOV EAX,12345678H
MOV BX,9999H
BT EAX,8;CF=0,EAX保持不變
BTC EAX,8;CF=0,EAX=12345778H
BTR EAX,8;CF=0,EAX=12345678H
BTS EAX,8;CF=0,EAX=12345778H
BSF AX,BX;AX=0
BSR AX,BX;AX=15
BT WORD PTR [AA],4;CF=1,[AA]的內容不變
BTC WORD PTR [AA],4;CF=1,[AA]=1223H
BTR WORD PTR [AA],4;CF=1,[AA]=1223H
BTS WORD PTR [AA],4;CF=1,[AA]=1234H
BSF WORD PTR [AA],BX;[AA]=0;
BSR WORD PTR [AA],BX;[AA]=15(十進制)
BT DWORD PTR [BB],12;CF=1,[BB]的內容保持不變
BTC DWORD PTR [BB],12;CF=1,[BB]=76779999H
BTR DWORD PTR [BB],12;CF=1,[BB]=76779999H
BTS DWORD PTR [BB],12;CF=1,[BB]=77779999H
BSF DWORD PTR [BB],12;[BB]=0
BSR DWORD PTR [BB],12;[BB]=31(十進制)
2.處理器控制指令
處理器控制指令主要是用來設置/清除標志,空操作以及與外部事件同步等。
2.1 CLC,將CF標志位清0。
2.2 STC,將CF標志位置1。
2.3 CLI,關中斷。
2.4 STI,開中斷。
2.5 CLD,清DF=0。
2.6 STD,置DF=1。
2.7 NOP,空操作,填補程序中的空白區,空操作本身不執行任何操作,主要是為了保持程序的連續性。
2.8 WAIT,等待BUSY引腳為高。
2.9 LOCK,封鎖前綴可以鎖定其後指令的操作數的存儲單元,該指令在指令執行期間一直有效。在多任務環境中,可以用它來保證獨占其享內存,只有以下指令才可以用LOCK前綴:
XCHG,ADD,ADC,INC,SUB,SBB,DEC,NEG,OR,AND,XOR,NOT,BT,BTS,BTR,BTC
3.0 說明處理器類型的偽指令
.8086,只支持對8086指令的匯編
.186,只支持對80186指令的匯編
.286,支持對非特權的80286指令的匯編
.286C,支持對非特權的80286指令的匯編
.286P,支持對80286所有指令的匯編
.386,支持對80386非特權指令的匯編
.386C,支持對80386非特權指令的匯編
.386P,支持對80386所有指令的匯編
只有用偽指令說明了處理器類型,匯編程序才知道如何更好去編譯,連接程序,更好地去檢錯。
九,FPU instructions(摘自fasm的幫助文檔中,有時間我會反它翻譯成中文的)
The FPU (Floating-Point Unit) instructions operate on the floating–point
values in three formats: single precision (32–bit), double precision (64–bit)
and double extended precision (80–bit). The FPU registers form the stack
and each of them holds the double extended precision floating–point value.
When some values are pushed onto the stack or are removed from the top,
the FPU registers are shifted, so st0 is always the value on the top of FPU
stack, st1 is the first value below the top, etc. The st0 name has also the
synonym st.
fld pushes the floating–point value onto the FPU register stack. The
operand can be 32–bit, 64–bit or 80–bit memory location or the FPU register,
it』s value is then loaded onto the top of FPU register stack (the st0 register)
and is automatically converted into the double extended precision format.
fld dword [bx] ; load single prevision value from memory
fld st2 ; push value of st2 onto register stack
fld1, fldz, fldl2t, fldl2e, fldpi, fldlg2 and fldln2 load the commonly
used contants onto the FPU register stack. The loaded constants are
+1.0, +0.0, log2 10, log2 e, pi, log10 2 and ln 2 respectively. These instructions
have no operands.
fild convert the singed integer source operand into double extended precision
floating-point format and pushes the result onto the FPU register stack.
The source operand can be a 16–bit, 32–bit or 64–bit memory location.
fild qword [bx] ; load 64-bit integer from memory
fst copies the value of st0 register to the destination operand, which can
be 32–bit or 64–bit memory location or another FPU register. fstp performs
the same operation as fst and then pops the register stack, getting rid of
st0. fstp accepts the same operands as the fst instruction and can also
store value in the 80–bit memory.
fst st3 ; value of st0 into st3 register
fstp tword [bx] ; store value in memory and pop stack
fist converts the value in st0 to a signed integer and stores the result
in the destination operand. The operand can be 16–bit or 32–bit memory
location. fistp performs the same operation and then pops the register
stack, it accepts the same operands as the fist instruction and can also store
integer value in the 64–bit memory, so it has the same rules for operands as
fild instruction.
fbld converts the packed BCD integer into double extended precision
floating–point format and pushes this value onto the FPU stack. fbstp
converts the value in st0 to an 18–digit packed BCD integer, stores the
result in the destination operand, and pops the register stack. The operand
should be an 80–bit memory location.
fadd adds the destination and source operand and stores the sum in the
destination location. The destination operand is always an FPU register,
if the source is a memory location, the destination is st0 register and only
source operand should be specified. If both operands are FPU registers, at
least one of them should be st0 register. An operand in memory can be a
32–bit or 64–bit value.
fadd qword [bx] ; add double precision value to st0
fadd st2,st0 ; add st0 to st2
faddp adds the destination and source operand, stores the sum in the destination
location and then pops the register stack. The destination operand
must be an FPU register and the source operand must be the st0. When no
operands are specified, st1 is used as a destination operand.
38 CHAPTER 2. INSTRUCTION SET
faddp ; add st0 to st1 and pop the stack
faddp st2,st0 ; add st0 to st2 and pop the stack
fiadd instruction converts an integer source operand into double extended
precision floating–point value and adds it to the destination operand.
The operand should be a 16–bit or 32–bit memory location.
fiadd word [bx] ; add word integer to st0
fsub, fsubr, fmul, fdiv, fdivr instruction are similar to fadd, have
the same rules for operands and differ only in the perfomed computation.
fsub substracts the source operand from the destination operand, fsubr
substract the destination operand from the source operand, fmul multiplies
the destination and source operands, fdiv divides the destination operand by
the source operand and fdivr divides the source operand by the destination
operand. fsubp, fsubrp, fmulp, fdivp, fdivrp perform the same operations
and pop the register stack, the rules for operand are the same as for the faddp
instruction. fisub, fisubr, fimul, fidiv, fidivr perform these operations
after converting the integer source operand into floating–point value, they
have the same rules for operands as fiadd instruction.
fsqrt computes the square root of the value in st0 register, fsin computes
the sine of that value, fcos computes the cosine of that value, fchs
complements its sign bit, fabs clears its sign to create the absolute value,
frndint rounds it to the nearest integral value, depending on the current
rounding mode. f2xm1 computes the exponential value of 2 to the power of
st0 and substracts the 1.0 from it, the value of st0 must lie in the range ?1.0
to +1.0. All these instruction store the result in st0 and have no operands.
fsincos computes both the sine and the cosine of the value in st0 register,
stores the sine in st0 and pushes the cosine on the top of FPU register
stack. fptan computes the tangent of the value in st0, stores the result in
st0 and pushes a 1.0 onto the FPU register stack. fpatan computes the
arctangent of the value in st1 divided by the value in st0, stores the result
in st1 and pops the FPU register stack. fyl2x computes the binary logarithm
of st0, multiplies it by st1, stores the result in st1 and pop the FPU
register stack; fyl2xp1 performs the same operation but it adds 1.0 to st0
before computing the logarithm. fprem computes the remainder obtained
from dividing the
⑶ 匯編語言 esi,edi寄存器問題
都屬於通用寄存器,所以一般場景下都可以隨便用。就是有些傳送指令規定了esi是源,edi是目的
⑷ x86匯編 ,基礎,關於[ebp]
mov edi,[ebp+8] ; ebp+8是一個局部變數,類型是指針char*,即字元串的首地址。功能是把字元串的首地址賦值給edi
mov esi,edi; esi=edi=字元串的首地址
find_end:
mov al,[esi] ;得到當前的地址里的字元值
inc esi ;指向下一個字元地址
; equal to lodsb increment esi
test al,al ;測試是否為字元串結束符\0
jnz find_end ;若不是結束符,則跳轉到find_end,循環。
;esi point after \0, we need to go back 2 char
sub esi,2 ;調整esi,因為在測試al等於\0結束符時,esi已經inc了一次。調整後,esi指向字元串的最後一個字元。
ebp+8,是局部變數,是char*指針,[ebp+8]是指針的值,即字元串的地址。
還有,ebp+8僅僅只是一個指針,它指向的字元串可以在任何地址。
不要把ebp+8當成字元串,它僅僅是指向字元串。
⑸ edi,esi寄存器是什麼寄存器有什麼作用
EDI和ESI分別是16位寄存器DI和SI的32位擴展
它們是目的變址寄存器和源變址寄存器,用於串操作指令中。
同時,它們也可以作為通用寄存器使用。
⑹ 匯編語言中所有寄存器的作用
寄存器有點多,介紹常用的,通用寄存器8個,EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP,最後+eip+EFL;
eax多用於計算,函數的返回值等;
ecx多用於計數(count),比如循環中的那個計數,結合eax,ESI,edi。
ebp用於堆棧指針追蹤,指低(debug版本),esp用於堆棧跟蹤,多跟ebp一起使用(指向頂部,最高,也就是最前)。
esi,edi多用於復制內存。
eip就是固定作用了,CPU指令全靠它了,指那打哪。
efl就是標志寄存器了,16位就夠用了,現在64位,完全空著呢,比如位溢出(兩個計算數據太大溢出,不夠減溢出),凡是條件(除了變態的jmp),無論if,while等,還是運算,或者符號位(數據是正還是負),或者數據檢查,奇偶等,都是看它的。也就是說,無論CPU運算還是控制,都看它對應的不同位。
下面給你通用寄存器幾個例子:假如eax的值為10,要將一塊內存賦值為cc,循環10次,而EDI裡面是內存地址的話,那麼代碼就是:mov EAX,0Xcc
mov ecx,0xa
rep stos byte ptr [edi]
這樣,內存就全部被成為「ccccccccccccccccc」,這樣的代碼到處都是,尤其沒有初始化之後,就能見到這樣的CC,中文顯示就是「燙燙燙」.
從一個內存賦值到另一個內存地址是這樣的,假如esi是指針p1的地址,edi是指針p2的地址,那麼*p2=*p1就是:
rep movs byte ptr es:[edi],byte ptr ds:[esi]
所以,edi,ESI,以及EBX,
⑺ 匯編語言寄存器都叫什麼
1、寄存器
32位寄存器有16個,分別是:
4個數據寄存器(EAX、EBX、ECX、EDX)。
2個變址和指針寄存器(ESI和EDI);2個指針寄存器(ESP和EBP)。
6個段寄存器(ES、CS、SS、DS、FS、GS)。
1個指令指針寄存器(EIP);1個標志寄存器(EFlags)。
2、數據寄存器
數據寄存器主要用來保存操作數和運算結果等信息,從而節省讀取操作數所需佔用匯流排和訪問存儲器的時間。
32位CPU有4個32位通用寄存器:EAX、EBX、ECX和EDX。對低16位數據的取存,不會影響高16
位的數據,這些低16位寄存器分別命名為AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。
4個16位寄存器又可分割成8個獨立的8位寄存器(AX:ah~al、BX:bh~bl、CX:ch~cl:DX:dh~dl)。
每個寄存器都有自己的名稱,可獨立存取。程序員可利用數據寄存器的這種「可合可分」的特性,靈活地處理字/
位元組的信息。
AX和al通常稱為累加器,用累加器進行的操作可能需要更少時間,累加器可用於乘、除、輸入/輸出等操作,
它們的使用頻率很高。
BX稱為基地址寄存器,它可作為存儲器指針來使用。
CX稱為計數寄存器,在循環和字元串操作時,要用它來控制循環次數;在位操作中,當移多位時,要用cl來
指明位移的位數。
DX稱為數據寄存器,在進行乘、除運算時,它可以為默認的操作數參與運算,也可用於存放I/O的埠地址。
在16位CPU中,AX、BX、CX和DX不能作為基址和變址寄存器來存放存儲單元的地址,但在32位CPU
中,其32位寄存器EAX、EBX、ECX和EDX不僅可傳送數據、暫存數據、保存算術邏輯運算結果,而且也可
作為指針寄存器,所以,這些32位寄存器更具有通用性。
3、變址寄存器
32位CPU有2個32位通用寄存器ESI和EDI,其低16位對應先前CPU中的SI和DI,對低16位數據的
存取,不影響高16位的數據。
ESI、EDI、SI和DI稱為變址寄存器,它們主要用於存放存儲單元在段內的偏移量,用它們可實現多種存儲器
操作數的定址方式,為以不同的地址形式訪問存儲單元提供方便。
變址寄存器不可分割成8位寄存器,作為通用寄存器,也可存儲算術邏輯運算的操作數和運算結果。
它們可作一般的存儲器指針使用,在字元串操作指令的執行過程中,對它們有特定的要求,而且還具有特殊的
功能。
4、指針寄存器
32位CPU有2個32位通用寄存器EBP和ESP,其低16位對應先前CPU中的BP和SP,對低16位數
據的存取,不影響高16位的數據。
EBP、ESP、BP和SP稱為指針寄存器,主要用於存放堆棧內存儲單元的偏移量,用它們可實現多種存儲器
操作數的定址方式,為以不同的地址形式訪問存儲單元提供方便。
指針寄存器不可分割成8位寄存器,作為通用寄存器,也可存儲算術邏輯運算的操作數和運算結果。
它們主要用於訪問堆棧內的存儲單元,並且規定:
BP為基指針寄存器,用它可直接存取堆棧中的數據。
SP為堆棧指針寄存器,用它只可訪問棧頂。
5、段寄存器
段寄存器是根據內存分段的管理模式而設置的。內存單元的物理地址由段寄存器的值和一個偏移量組合而成
的,這樣可用兩個較少位數的值組合成一個可訪問較大物理空間的內存地址。
32位CPU有6個段寄存器,分別如下:
CS:代碼段寄存器 ES:附加段寄存器
DS:數據段寄存器 FS:附加段寄存器
SS:堆棧段寄存器 GS:附件段寄存器
在16位CPU系統中,只有4個段寄存器,所以,程序在任何時刻至多有4個正在使用的段可直接訪問,在
32位微機系統中,它有6個段寄存器,所以在此環境下開發的程序最多可同時訪問6個段。
32位CPU有兩個不同的工作方式:實方式和保護方式。在每種方式下,段寄存器的作用是不同的,有關規定
簡單描述如下:
實方式:段寄存器CS、DS、ES和SS與先前CPU中的所對應的段寄存器的含義完全一致,內存單元的邏輯
地址仍為「段地址:偏移地址」的形式,為訪問某內存段內的數據,必須使用該段寄存器和存儲單元的偏移地址。
保護方式:在此方式下,情況要復雜得多,裝入段寄存器的不再是段值,而是稱為「選擇子」的某個值。
6、指令指針寄存器
32位CPU把指令指針擴展到32位,並記作EIP,EIP的低16位與先前CPU中的IP作用相同。
指令指針EIP、IP是存放下次將要執行的指令在代碼段的偏移地址,在具有預取指令功能的系統中,下次要執
行的指令通常已被預取到指令隊列中,除非發生轉移情況,所以,在理解它們的功能時不考慮存在指令隊列的情
況。
在實方式下,由於每個段的最大范圍為64KB,所以,EIP的高16位肯定都為0,此時,相當於只用其低16
位的IP來反映程序中的指令的執行次序。
7、標志寄存器
1.運算結果標志位。一共6個,包括:CF進位標志位、PF奇偶標志位、AF輔助進位標志位、ZF零標志位、
SF符號標志位、OF溢出標志位。
2.狀態控制標志位。一共3個,包括:TF追蹤標志位、IF中斷允許標志位、DF方向標志位。
以上標志位在第7章里都講過了,在這里就不再解釋了,現在講講32位標志寄存器增加的4個標志位。
1. I/O特權標志IOPL。
IOPL用兩位二進制位來表示,也稱為I/O特權級欄位,該欄位指定了要求執行I/O指令的特權級,如果當前
的特權級別在數值上小於等於IOPL的值,那麼,該I/O指令可執行,否則將發生一個保護異常。
2. 嵌套任務標志NT。
NT用來控制中斷返回指令IRET的執行。具體規定如下:
(1) 當NT=0,用堆棧中保存的值恢復EFlags、CS和EIP,執行常規的中斷返回操作。
(2) 當NT=1,通過任務轉換實現中斷返回。
3. 重啟動標志RF。
RF用來控制是否接受調試故障。規定:RF=0時,表示接受,否則拒絕。
4. 虛擬8086方式標志VM。
如果VM=1,表示處理機處於虛擬的8086方式下的工作狀態,否則,處理機處於一般保護方式下的工作狀態。
8、32位地址的定址方式
最後說一下32位地址的定址方式。在前面我們學習了16位地址的定址方式,一共有5種,在32位微機系統
中,又提供了一種更靈活、方便但也更復雜的內存定址方式,從而使內存地址的定址范圍得到了進一步擴大。
在用16位寄存器來訪問存儲單元時,只能使用基地址寄存器(BX和BP)和變址寄存器(SI和DI)來作為
偏移地址的一部分,但在用32位寄存器定址時,不存在上述限制,所有32位寄存器(EAX、EBX、ECX、
EDX、ESI、EDI、EBP、和ESP)都可以是偏移地址的一個組成部分。
當用32位地址偏移量進行定址時,偏移地址可分為3部分:
1. 一個32位基址寄存器(EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP)。
2. 一個可乘以1、2、4、8的32位變址寄存器(EAX、EBX、ECX、EDX、ESI、EDI和EBP)。
3. 一個8位~32位的偏移常量。
比如,指令:mov ebx, [eax+edx*2+300]
Eax就是基址寄存器,edx就是變址寄存器,300H就是偏移常量。
上面那3部分可進行任意組合,省去其中之一或之二。
下面列舉幾個32位地址定址指令:
Mov ax, [123456]
Mov eax, [ebx]
Mov ebx, [ecx*2]
Mov ebx, [eax+100]
Mov ebx, [eax*4+200]
Mov ebx, [eax+edx*2]
Mov ebx, [eax+edx*4+300]
Mov ax, [esp]
由於32位定址方式能使用所有的通用寄存器,所以,和該有效地址相組合的段寄存器也就有新的規定,具體
規定如下:
1. 地址中寄存器的書寫順序決定該寄存器是基址寄存器還是變址寄存器。
如:[ebx+ebp]中的ebx是基址寄存器,ebp是變址寄存器,而[ebp+ebx]中的ebp是基址寄存器,ebx是變
址寄存器,可以看出,左邊那個是基址寄存器,另一個是變址寄存器。
2. 默認段寄存器的選用取決於基址寄存器。
3. 基址寄存器是ebp或esp時,默認的段寄存器是SS,否則,默認的段寄存器是DS。
4. 在指令中,如果顯式地給出段寄存器,那麼顯式段寄存器優先。
下面列舉幾個32位地址定址指令及其內存操作數的段寄存器。
指令列舉: 訪問內存單元所用的段寄存器
mov ax, [123456] ;默認段寄存器為DS。
mov ax, [ebx+ebp] ;默認段寄存器為DS。
mov ebx, [ebp+ebx] ;默認段寄存器為SS。
mov ebx, [eax+100] ;默認段寄存器為DS。
mov edx, ES:[eax*4+200] ;顯式段寄存器為ES。
mov [esp+edx*2], ax ;默認段寄存器為SS。
mov ebx, GS:[eax+edx*8+300] ;顯式段寄存器為GS。
mov ax, [esp] ;默認段寄存器為SS。
⑻ 80X86微處理器有幾代各代的名稱是什麼
1.7 Intel 80x86處理器簡介
到此,您已經看到了兩個將要實際編譯和運行的HLA程序。然而至今為止,出現在程序中的所有語句要麼是數據聲明,要麼是對HLA標准庫常式的調用,還不是真正的匯編語言。在我們學習真正的匯編語言之前,必須理解Intel 80x86處理器系列的基本結構,否則機器指令將沒有任何意義。
Intel 系列CPU一般都被歸為馮·諾依曼式機器。馮·諾依曼計算機系統包括三個主要模塊:中央處理單元(CPU),存儲器和輸入/輸出設備(I/O)。這三部分通過系統匯流排(由數據、地址和控制匯流排組成)相連。圖1-4中的模塊圖表示了這種關系。
圖1-4 馮·諾依曼計算機系統模塊圖
CPU與存儲器和I/O設備之間的通信方法是向地址匯流排發送一個數值來選取一個存儲單元或者I/O設備埠,它們都有惟一的二進制地址。因此,CPU、I/O以及存儲器設備都通過將數據放到數據匯流排上來傳遞彼此之間的數據。控制匯流排則包含用於確定數據傳輸方向(在內存之間,以及I/O設備之間)的信號。
在CPU當中,寄存器是其最主要的特徵。80x86 CPU的寄存器可以分成四類:通用寄存器、特殊目的寄存器、段寄存器以及特殊目的核心模式寄存器。本書不會介紹最後兩類寄存器。段寄存器在現代的32位操作系統(例如:Windows,BeOS和Linux)當中用得不多;由於本書是專門針對32位操作系統所編寫的程序,所以不需要討論段寄存器。特殊目的核心模式寄存器專門用來編寫操作系統、調試器以及其他系統級工具。這些軟體的構建遠遠超出了本書的范圍,所以也無需討論特殊目的核心模式寄存器。
80x86(Intel系列)CPU提供了幾個通用寄存器。其中包含八個32位寄存器,如下所示:
EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP
每個名稱的前綴『E』代表擴展(extended)的意思。該前綴將32位寄存器與如下所示的八個16位寄存器區分開來:
AX、BX、CX、DX、SI、DI、BP、SP
最後,80x86 CPU還提供了八個8位的寄存器,它們的名稱如下所示:
AL、AH、BL、BH、CL、CH、DL、DH
遺憾的是,這些並非都是分離的寄存器。即80 x 86並未提供24個獨立的寄存器。實際上,80x86將16位寄存器重疊於32位寄存器之上,也將8位寄存器重疊於16位寄存器之上。圖1-5給出了這種關系。
圖1-5 80x86(Intel系列CPU)的通用寄存器
關於通用寄存器,需要注意的是它們並不獨立。修改一個寄存器可能會影響其他三個寄存器。例如,對EAX的修改可能會影響寄存器AL,AH以及AX。這一點相當重要。在匯編語言初學者所編寫的程序當中,一個很常見的錯誤就是寄存器值的破壞,因為這些編程人員尚未完全理解圖1-5的含義。
EFLAGS是一個32位寄存器,它包含幾個1位的布爾值(true/false)。EFLAGS寄存器中的大多數要麼是為核心模式(操作系統)函數保留的,要麼就是程序員不感興趣的。其中有8位(或標志)是程序員編寫匯編語言程序需要用到的。它們分別是溢出標志、方向標志、中斷禁止[4]標志、符號標志、零標志、輔助進位標志、奇偶標志以及進位標志。圖1-6顯示了EFLAGS寄存器低16位中標志的布局情況。
在應用程序員感興趣的8個標志中,有4個標志特別重要:溢出標志、進位標志、符號標志以及零標志。這4個標志統稱為條件碼[5]。根據這些標志的狀態就可以測試前一次計算的結果。例如,在對兩個值進行比較以後,條件碼標志就會告訴您其中一個值是小於,等於還是大於另一個值。
圖1-6 標志寄存器的布局(EFLAGS的低16位)
令匯編語言初學者驚訝的一個重要事實是,在80x86 CPU中進行的所有計算幾乎都和寄存器有關。例如,將兩個變數相加,把它們的和存入第3個變數中,必須先將其中一個變數裝入一個寄存器中,並將第2個操作數和寄存器的值相加,然後將寄存器中的值存入目的變數。寄存器在每次計算中都充當媒介。因此,在80x86匯編語言程序中寄存器是非常重要的。
還有一點很重要,雖然某些寄存器被稱為是「通用」的,但並不能就此推斷每個寄存器都能隨意使用。以寄存器對SP/ESP為例,它們就有特殊的目的,而不能用於任何其他的目的(它們是棧指針)。同樣,寄存器BP/EBP也具有特殊目的,它們的使用受到限制而無法當作通用寄存器使用。所有80x86寄存器都有它們自己特殊的目的,因此它們都限定在一個范圍內使用。目前,您應該避免將ESP和EBP寄存器用於一般的計算當中;還應該記住,餘下的寄存器在程序中不可以完全互換。存儲子系統
運行32位操作系統的80x86處理器可以訪問多達232個不同的存儲單元,或者四十多億位元組。在幾年以前,4G位元組的存儲器是最大的;然而,現代的機器已經遠遠超出了這一限制。由於在使用像Windows和Linux這樣的32位操作系統時,80x86體系結構支持最大4G位元組的地址空間,下面的討論將假設最大有4G位元組的空間。
當然,您應該問的第一個問題是:「確切地說,什麼是一個存儲單元?」80x86支持位元組可定址存儲器(byte addressable memory)。因此基本的存儲單元就是一個位元組,這足以容納一個單字元或是一個(非常)小的整數值(第2章將更詳細地討論這一點)。
將內存看作是位元組線性數組。首位元組的地址為0,末位元組的地址為。對於奔騰處理器來說,下面的偽Pascal數組聲明就是一個對內存非常好的比擬:
Memory: array [0..4294967295] of byte;
C/C++和Java用戶可能偏愛下面這種語法:
byte Memory[4294967296];
為了執行Pascal語句「Memory[125]:=0;」的等效語句,CPU將數值0放在數據匯流排上,將地址125放到地址匯流排上,並設置寫信號線(通常要將該線置0),如圖1-7所示。
圖1-7 存儲器的寫操作
若執行「CPU:=Memory[125];」的等效語句,CPU會將地址125放到地址匯流排上,並設置讀信號線(因為CPU正在從存儲器讀取數據),然後從數據匯流排上讀取數據結果(如圖1-8所示)。
圖1-8 存儲器的讀操作
這里的討論只適用於訪問內存中單個位元組的情況。那麼當處理器訪問一個字或者雙字時又會如何呢?由於存儲器由一個位元組數組構成,那麼我們應該怎樣處理大於一個位元組的數據呢?很簡單,要存儲更大的值,80x86使用連續的存儲單元序列就可以了。圖1-9給出了80x86如何在存儲器中存儲位元組、字(雙位元組)以及雙字(四位元組)。每個對象的內存地址就是它的首位元組地址(最低地址)。
現代的80x86處理器實際上並不直接與存儲器相連。而是CPU上有一個專門的存儲緩沖器稱為高速緩存(cache),它充當CPU與主存儲器之間的高速媒介。雖然高速緩存可以自動處理細節,但應該明白一個事實,即如果該對象的地址為對象長度的整數倍,那麼訪問內存中的數據對象的效率更高。因此,用4的整數倍的地址來對准四位元組(雙字)對象的確是個好主意。同樣,讓雙位元組對象對准偶數地址是最有效的。在後面的章節中,您將學習如何設置內存對象的對准。
圖1-9 存儲器中位元組、字和雙字的存儲
在結束討論內存對象以前,應該理解內存與HLA變數之間的相關性。使用像HLA這樣的匯編器/編譯器的一個好處是不必擔心內存地址值。只需在HLA中聲明一個變數,HLA負責將該變數與惟一一組內存地址集合相關聯。例如,對於下面的聲明段:
static
i8 :int8;
i16 :int16;
i32 :int32;
HLA將在內存中找到某個未使用的8位位元組,將其與變數i8相關聯;還將找到一對連續未使用的位元組,並將它們與i16相關聯。最後,HLA將找到4個連續未使用的位元組,並將i32的值與這4個位元組(32位)相關聯。以後就要通過變數的名稱來引用它們,而不必關心它們的地址值。但是,您仍然應該知道HLA在後台完成了這些工作。
⑼ 64和86有什麼區別
1、表達的意思不同。
X64表達的意思是CPU為64位的操作系統。X86表達的意思是CPU為32位的操作系統
2、配置要求不同。
X64的操作系統只能安裝在CPU為64位的計算機上。X86的操作系統可以安裝在32位(32位CPU)或64位(64位CPU)電腦上。
3、運算速度不同。
X64的操作系統處理器一次可提取64位數據(只要兩個指令,一次提取8個位元組的數據),比32位(需要四個指令,一次提取4個位元組的數據)提高了一倍,理論上性能會相應提升1倍。
4、支持的內存容量不同。
64位CPU和操作系統理論上最高可支持16EB內存。32位CPU和操作系統最大隻可支持4GB內存。
5、引入個人計算機時間不同。
64位操作系統是2003年引入個人計算機領域。32位操作系統約20世紀90年代。