 # Hey, 野声!

## IBM-PC Assembly Language Programming Review

Final review compilation... Really working hard on the review...
The experiments assigned by the lab instructor, I feel grateful for them~
Let's talk about input/output, branching flow, basic instructions, and then discuss the questions we have done.

## Input/Output#

### Converting ASCII code value of an integer to numerical value#

• 0-9 30H-39H
Subtract 30H or AND with 1111(15)
• A-F 41H-46H
Subtract 37H(55)
• a-z 61H-66H
Subtract 57H(75)

### Input a single hexadecimal integer#

``````IN_1_HEX:
MOV AH, 01H
INT 21H     ; The input value is stored in AL
CMP AL, '9' ; The input value is represented in memory as an ASCII code value
JBE IN
SUB AL, 07H
IN:
SUB AL, 30H
``````

### Input a two-digit hexadecimal integer#

The maximum value represented by two-digit hexadecimal is `FF`, which is 255, and it can be stored in eight bits.

``````IN_2_HEX:
CALL IN_1_HEX ; High-order hexadecimal -> AL
MOV  AH, 10H
MUL  AH
MOV  AH, AL
CALL IN_1_HEX ; Low-order hexadecimal -> AL
``````

### Input a single decimal integer#

Remember to protect the previous data when using it, first PUSH then POP

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

### Input a two-digit decimal integer#

``````IN_2_DEC:
CALL IN_1_DEC
MOV  AH, 10  ; In hexadecimal, this is 10H
MUL  AH
MOV  AH, AL
CALL IN_1_DEC
``````

### Output a single hexadecimal integer#

``````DISP_1_HEX:
CMP DL, 09H
JBE L1
L1:

MOV AH, 02H
INT 21H
``````

### Output a two-digit hexadecimal integer#

``````DISP_2_HEX:
MOV AL, DL
MOV AH, 0
MOV DL, 10H
DIV DL        ; Divisor is 8 bits, quotient is stored in AL, remainder in AH
MOV DL, AL
CALL DISP_1_HEX
MOV DL, AH
CALL DISP_1_HEX
``````

### Output a single decimal integer#

``````DISP_1_DEC:
PUSH AX
MOV AH,02H
INT 21H
POP AX
RET
``````

### Output a two-digit decimal integer#

``````DISP_2_DEC:    ; DL division by ten
PUSH AX
MOV AL,DL
MOV AH,0
MOV DL,10
DIV DL        ; Divisor is 8 bits, quotient is stored in AL, remainder in AH
MOV DL,AL
CALL DISP_1_DEC
MOV DL,AH
CALL DISP_1_DEC
POP AX
RET
``````

### Output a multi-digit decimal integer with a sign bit#

``````DISP:            ; Output the number in AX in decimal
PUSHF
PUSH DX
PUSH AX
PUSH BX
PUSH CX

MOV  CX, 0
MOV  BX, 10    ; Divisor is 10

TEST AX, 8000H ; Check if the most significant bit of AX is 1 or 0
JE   DISP1     ; If the result of the previous instruction is 0, jump
CALL FF        ; Output the negative sign
NEG  AX        ; Negate +1

DISP1:
MOV  DX, 0
DIV  BX        ; Divisor is 16-bit, quotient in AX, remainder in DX
PUSH DX
INC  CX
OR   AX, AX    ; Check if quotient is 0
JNE  DISP1     ; If not 0, continue division

DISP2:
POP  DX
ADD  DL, 30H   ; Output as ASCII code
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
``````

## Loop and Branching Structure#

### Comparison#

The most important thing is comparison,

`TEST`, `AND`, `CMP`, `SUB`, and so on... can all be used for comparison.

#### TEST Instruction#

Instruction format: `TEST DST, SRC`
The `TEST` instruction can be used to check if a particular bit is 1, as it essentially performs an AND operation, i.e., `DST & SRC`, without modifying the source and destination operands.

For example, the result of `00010000 & X` represents whether the fifth bit from the right in X is 1. If the result is 0, it means that the bit is 0, otherwise it is 1.

#### CMP Instruction#

Instruction format: `CMP DST, SRC`

It can be used to compare the sizes of two numbers, essentially performing a subtraction operation, i.e., `DST - SRC`, without modifying the source and destination operands.

### Jump Instructions#

Here, we determine the specific comparison of the two numbers being compared and decide which statement to execute.

In C-style languages, it would be like this:

``````if (a > b){
// Execute this if a > b
}else{
// Execute this if a <= b
}
``````

In assembly language, it would be:

``````  CMP AX, BX
JA AGB
# Execute this if AX <= BX
AGB:
# Execute this if AX > BX
``````

The `JA` above is a jump instruction. I won't go into detail about various instructions, refer to the book~
Here are a few important ones to remember~

• JE Two numbers are equal
• JNE Two numbers are not equal
• JA Unsigned, first number is greater than second number
This is how I remember it: A represents the first number among the two being compared, B represents the second number, so `JA` means the first number is greater.
• JG Signed comparison, first number is greater than second number
G stands for greater than
• JB Unsigned, first number is less than second number
• JL Signed comparison, first number is less than second number
L stands for less than
• JAE Unsigned, first number is greater than or equal to second number
• JGE Signed, first number is greater than or equal to second number
• JBE Unsigned, first number is less than or equal to second number
• JLE Signed, first number is less than or equal to second number

We all know that one hexadecimal digit can represent four binary digits, so to convert binary to hexadecimal, we need to convert four digits at a time.
The general process is as follows:

``````digraph g {
Shift left four binary digits
-> Take the low four digits
-> "Low four digits + 30H"
-> Output the low four digits;

Output the low four digits -> Shift left four binary digits [label="If there are more digits"]
}
``````

### Control Transfer Instructions#

Refer to page 85 of the book

## Questions#

### Input a twenty-digit signed hexadecimal number, sort it, and output the maximum, minimum, second maximum, and second minimum numbers in decimal#

``````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
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     ; Signed comparison
XCHG AX,[BX+2]
MOV [BX],AX
CONTINUE:
LOOP LOOP2
POP CX
LOOP LOOP1
MOV cx, NUM
MOV si,offset X
CALL HR

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

MOV si,offset X
CALL HR

; Minimum number
DEC NUM
SHL NUM, 1
MOV AX,[SI]
call DISP
call SPACE

; Maximum number
MOV si,offset X
MOV AX,[si]
call DISP
call SPACE

; Second minimum number

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

; Second maximum number
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
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; Check if negative
JE DISP1
CALL FF
;AND  AX,7FFFH
NEG  AX

DISP1:
MOV DX,0
DIV BX     ;AX, quotient; DX, remainder
PUSH DX
INC CX
OR AX,AX   ; Check if 0
JNE DISP1
DISP2:
MOV AH,2
POP DX
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
``````