野声

Hey, 野声!

谁有天大力气可以拎着自己飞呀
twitter
github

IBM-PC 彙編語言程式設計複習

期末復習彙編... 真的是好努力的復習...
實驗老師讓我們做的那幾個實驗,想想還覺得謝謝了~
談一下輸入輸出、分支流程、基本指令,再談一下做過的幾個題目。

輸入輸出#

整數的 ASCII 碼值轉為數值#

  • 0-9 30H-39H
    可以減去 30H 或者 與上 1111 (15)
  • A-F 41H-46H
    減去 37H (55)
  • a-z 61H-66H
    減去 57H (75)

輸入一位十六進制整數#

IN_1_HEX:
	MOV AH, 01H
	INT 21H     ;輸入的值存在AL裡
	CMP AL, '9' ;輸入的值在內存中都是以ASCII碼的值表示
	JBE IN
	SUB AL, 07H
IN:
	SUB AL, 30H

輸入兩位十六進制整數#

兩位十六進制表示的值最多是 FF ,也就是 255,用八位就可以存下。

IN_2_HEX:
	CALL IN_1_HEX ;高位十六進制->AL
	MOV  AH, 10H
	MUL  AH
	MOV  AH, AL
	CALL IN_1_HEX ;低位十六進制->AL
	ADD  AL, AH

輸入一位十進制整數#

實際使用的時候記得要保護之前的數據,先 PUSH 再 POP

IN_1_DEC:
	MOV AH, 01H ;AL
	INT 21H
	SUB AL, 30H

輸入兩位十進制整數#

IN_2_DEC:
	CALL IN_1_DEC
	MOV  AH, 10  ; 十六進制這裡為10H
	MUL  AH
	MOV  AH, AL
	CALL IN_1_DEC
	ADD  AL, AH

輸出一位十六進制整數#

DISP_1_HEX:
  CMP DL, 09H
  JBE L1
  ADD DL, 07H
L1:
  ADD DL, 30H

  MOV AH, 02H
  INT 21H

輸出兩位十六進制整數#

DISP_2_HEX:
  MOV AL, DL
  MOV AH, 0
  MOV DL, 10H
  DIV DL        ; 除數是 8 位 AL 存商, AH 存餘數
  MOV DL, AL
  CALL DISP_1_HEX
  MOV DL, AH
  CALL DISP_1_HEX

輸出一位十進制整數#

DISP_1_DEC:
  PUSH AX
  ADD DL,30H
  MOV AH,02H
  INT 21H
  POP AX
RET

輸出兩位十進制整數#

DISP_2_DEC:    ; DL 除十取餘法
  PUSH AX
  MOV AL,DL
  MOV AH,0
  MOV DL,10
  DIV DL        ; 除數是 8 位 AL 存商, AH 存餘數
  MOV DL,AL
  CALL DISP_1_DEC
  MOV DL,AH
  CALL DISP_1_DEC
  POP AX
RET

帶符號位的輸出多位十進制整數#

DISP:            ; 用十進制出AX中的數
  PUSHF
  PUSH DX
  PUSH AX
  PUSH BX
  PUSH CX

  MOV  CX, 0
  MOV  BX, 10    ; 除 10 取餘法

  TEST AX, 8000H ; 檢測AX首位是1還是0
  JE   DISP1     ; 如果上一句的結果為0,就跳
  CALL FF        ; 輸出負號
  NEG  AX        ; 取反+1

DISP1:
  MOV  DX, 0
  DIV  BX        ;除數是 16 位 AX,商;DX,餘數
  PUSH DX
  INC  CX
  OR   AX, AX    ; 是否商完
  JNE  DISP1     ; 沒商完繼續商

DISP2:
  POP  DX
  ADD  DL, 30H   ; 以ascii碼輸出
  MOV  AH, 02H
  INT  21H
  LOOP DISP2

  POP  CX
  POP  BX
  POP  AX
  POP  DX
  POPF
RET
FF:
  PUSH DX
  PUSH AX

  MOV  DL, '-'
  MOV  AH, 02H
  INT  21H

  POP  AX
  POP  DX
RET

循環分支結構#

比較#

最重要的就是 比較,

TESTANDCMPSUB 還有等等等等... 都可以拿來做比較。

TEST 指令#

指令格式:TEST DST, SRC
TEST 指令可以被用來檢測某一位是否為 1,因為其本質就是與運算,也就是 DST & SRC,但是不改變源操作數和目標操作數。

00010000 & X 的結果就表示 X 的倒數第五位是否為 1,要是與出來為 0,就說明這一位為 0,否則為 1。

CMP 指令#

指令格式:CMP DST, SRC

可以比較兩個數的大小,本質就是減法運算,也就是 DST - SRC,但是不改變源操作數和目標操作數。

跳轉指令#

這裡的就是判斷被比較的兩個數的具體大小,然後決定執行哪一句。

C-style 的語言中是這樣:

if (a > b){
  // a > b 的話執行這兒
}else{
  // a <= b 的話執行這兒
}

匯編中呢,就是:

  CMP AX, BX
  JA AGB
  # AX <= BX 的話執行這兒
AGB:
  # AX > BX 的話執行這兒

上面的 JA 就是一個跳轉指令,再詳細的各種指令我就不說了,看書~
下面稍微說幾個記得牢的~

  • JE 兩個數相等
  • JNE 兩個數不相等
  • JA 無符號 前者大於後者
    我是這樣記得, A 就是兩個比較的數裡前面那個,B 就是兩個比較的數裡後面那個,所以 JA 就是前面的大。
  • JG 有符號比較,前者大於後者
    G 的意思就是 greater than
  • JB 無符號 前者小於後者
  • JL 有符號比較 前者小於後者
    L = less than
  • JAE 無符號大於等於
  • JGE 有符號大於等於
  • JBE 無符號小於等於
  • JLE 有符號小於等於

二進制轉十六進制#

我們都知道,一位十六進制可以表示四位二進制,所以要把二進制轉為十六進制的話,得每四位每四位的轉換。
大概流程如下

digraph g {
循環左移四位二進制
	-> 取低四位
	-> "低四位+30H"
	-> 輸出低四位;

輸出低四位 ->循環左移四位二進制 [label="如果位數不為0"]
}

控制轉移指令#

書上 P85

題目#

輸入二十位帶符號十六進制數,排序後輸出十進制最大數、最小數、次大數、次小數#

DATA SEGMENT
  X  DW 20 DUP(?)
  NUM DW 6
DATA ENDS
S1 SEGMENT PARA STACK
  BUF1 DW 20H DUP (0)
  LEN1 EQU $-BUF1
S1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:S1
GO:
  MOV  AX,DATA
  MOV  DS,AX
  MOV  AX,S1
  MOV  SS,AX
  MOV  SP,LEN1

  MOV  CX,NUM
  MOV  SI,OFFSET X

L1:
  CALL IN_2_HEX
  MOV  AH, AL
  CALL IN_2_HEX
  MOV  [SI],AX
CC:
  CALL SPACE
  ADD  SI,2
  LOOP L1
  CALL HR
  MOV CX,NUM
  MOV SI,OFFSET X
  DEC CX

LOOP1:
  PUSH CX
  MOV BX,OFFSET X
LOOP2:
  MOV AX,[BX]
  CMP AX,[BX+2]
  JGE CONTINUE     ;有符號比較
  XCHG AX,[BX+2]
  MOV [BX],AX
CONTINUE:
  ADD BX,2
  LOOP LOOP2
  POP CX
  LOOP LOOP1
  MOV cx, NUM
  MOV si,offset X
  CALL HR

dispdec2:
  MOV AX,[si]
  call DISP
  call SPACE
  add si,2
  loop dispdec2
  CALL HR

  MOV si,offset X
  CALL HR

  ; 最小數
  DEC NUM
  SHL NUM, 1
  ADD SI,NUM
  MOV AX,[SI]
  call DISP
  call SPACE

  ; 最大數
  MOV si,offset X
  MOV AX,[si]
  call DISP
  call SPACE

  ; 次小數

  ADD SI,NUM
  MOV AX,[SI-2]
  call DISP
  call SPACE

  ; 次大數
  MOV si,offset X
  MOV AX,[SI+2]
  call DISP
  call HR

  MOV AH,4CH
  INT 21H

IN_2_HEX:
  PUSHF
  PUSH BX
  MOV BH,AH
  CALL IN_1_HEX  ;AL  high
  MOV AH,10H
  MUL AH ;
  MOV AH,AL
  CALL IN_1_HEX  ;AL  low
  ADD AL,AH
  MOV AH,BH
  POP BX
  POPF
RET

IN_1_HEX:
  PUSHF
  PUSH BX
  MOV BH,AH

  MOV AH,01H
  INT 21H

  cmp AL,'9'
  JBE IN_B
  SUB AL,07H
IN_B:   ; 'A-F'
  SUB AL,30H
  MOV AH,BH
  POP BX
  POPF
RET


DISP:
  PUSHF
  PUSH DX
  PUSH AX
  PUSH BX
  PUSH CX

  MOV CX,0
  MOV BX,10

  test AX,8000H;是否為負
  JE DISP1
  CALL FF
  ;AND  AX,7FFFH
  NEG  AX

DISP1:
  MOV DX,0
  DIV BX     ;AX,商;DX,餘數
  PUSH DX
  INC CX
  OR AX,AX   ;是否為0
  JNE DISP1
DISP2:
  MOV AH,2
  POP DX
  ADD DL,30H
  INT 21H
  LOOP DISP2
  POP CX
  POP BX
  POP AX
  POP DX
  POPF
RET


SPACE:
  PUSH DX
  PUSH AX
  MOV  DL,20H
  MOV  AH,02H
  INT  21H
  POP  AX
  POP  DX
RET

HR:
  PUSH AX
  PUSH DX
  MOV  AH,02H
  MOV  DL,0AH
  INT  21H
  MOV  DL,0DH
  INT  21H
  POP  DX
  POP  AX
RET
FF:
  PUSH DX
  PUSH AX
  MOV  DL,'-'
  MOV  AH,02H
  INT  21H
  POP  AX
  POP  DX
RET
CODE ENDS
END GO
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。