25/05/2018, 07:40

Các cấu trúc cơ bản trong lập trình hợp ngữ

Cấu trúc tuần tự là cấu trúc đơn giản nhất. Trong cấu trúc tuần tự, các lệnh được sắp xếp tuần tự, lệnh này tiếp theo lệnh kia. Lệnh 1 Lệnh 2 … Lệnh n ...

Cấu trúc tuần tự là cấu trúc đơn giản nhất. Trong cấu trúc tuần tự, các lệnh được sắp xếp tuần tự, lệnh này tiếp theo lệnh kia.

Lệnh 1

Lệnh 2 …

Lệnh n

Cộng 2 giá trị của thanh ghi BX và CX, rồi nhân đôi kết quả, kết quả cuối cùng chứa trong AX

MOV AX,BX 

ADD AX,CX
; Cộng BX với CX

SHL AX,1
; Nhân đôi

IF Điều kiện THEN Công việc

IF Điều kiện THEN Công việc1 ELSE Công việc2

Gán BX = |AX|

CMP AX,0    
;AX > 0?

JNL DUONG   
; AX dương

NEG AX    
; Nếu AX < 0 thì đảo dấu

DUONG: MOV BX,AX NEXT:

Gán CL giá trị bit dấu của AX

CMP AX,0    
; AX > 0?

JNS AM    
; AX âm

MOV CL,1

JMP NEXT    
; CL = 1 (AX dương)

AM: MOV CL,0   
;CL = 0 (AX âm)

NEXT:

CASE Biểu thức

Giá trị 1: Công việc 1

Giá trị 2: Công việc 2

Giá trị n: Công việc n

END

Nếu AX > 0 thì BH = 0, nếu AX < 0 thì BH = 1. Ngược lại BH = 2

CMP AX,0

JL AM

JE KHONG

JG DUONG 

DUONG: MOV BH,0

JMP NEXT

AM: MOV BH,1

JMP NEXT

KHONG: MOV BH,2

NEXT:

FOR Số lần lặp DO Công việc

Cho vùng nhớ M dài 200 bytes trong đoạn dữ liệu, chương trình đếm số chữ A trong vùng nhớ M như sau:

MOV CX,200
; Đếm 200 bytes

MOV BX,OFFSET M
; Lấy địa chỉ vùng nhớ

XOR AX,AX
; AX = 0

NEXT: CMP BYTE PTR [BX],'A'   
;So sánh với chữ A

JNZ ChuA      
; Nếu không phải là chữ A thì tiếp

INC AX      
; tục, ngược lại thì tăng AX

ChuA: INC BX

LOOP NEXT

WHILE Điều kiện DO Công việc

Chương trình đọc vùng nhớ bắt đầu tại địa chỉ 1000h vào thanh ghi AH, đến khi gặp ký tự '$' thì thoát:

MOV BX,1000h 

CONT: CMP AH,'$'

JZ NEXT

MOV AH,DS:[BX] JMP CONT 

NEXT: 

REPEAT Công việc UNTIL Điều kiện

Chương trình đọc vùng nhớ bắt đầu tại địa chỉ 1000h vào thanh ghi AH, đến khi gặp ký tự '$' thì thoát:

MOV BX,1000h 

CONT: MOV AH,DS:[BX]

CMP AH,'$'

JZ NEXT

JMP CONT

NEXT:

Ngắt 21h

  • Hàm 01h: nhập một ký tự từ bàn phím và hiện ký tự nhập ra màn hình.

Nếu không có ký tự nhập, hàm 01h sẽ đợi cho đến khi nhập.

- Gọi: AH = 01h

- Trả về: AL chứa mã ASCII của ký tự nhập

MOV AH,01h 

INT 21h   
; AL chứa mã ASCII của ký tự nhập
  • Hàm 02h: xuất một ký tự trong thanh ghi DL ra màn hình tại vị trí con trỏ hiện hành

- Gọi AH = 02h, DL = mã ASCII của ký tự

- Trả về: không có

MOV AH,02h 

MOV DL,'A' 

INT 21h
  • Hàm 08h: giống hàm 01h nhưng không hiển thị ký tự ra màn hình
  • Hàm 09h: xuất một chuỗi ký tự ra màn hình tại vị trí con trỏ hiện hành, địa chỉ chuỗi được chứa trong DS:DX và phải được kết thúc bằng ký tự $

- Gọi AH = 09h, DS:DX = địa chỉ chuỗi

- Trả về: không có

.DATA 

Msg DB 'Hello$' 

...

MOV AH,09h LEA DX,Msg 

INT 21h
  • Hàm 0Ah: nhập một chuỗi ký tự từ bàn phím (tối đa 255 ký tự), dùng phím ENTER kết thúc chuỗi

- Gọi AH = 0Ah, DS:DX = địa chỉ lưu chuỗi

- Trả về: không có

Chuỗi phải có dạng sau:

- Byte 0: Số byte tối đa cần đọc (kể cả ký tự Enter)

- Byte 1: số byte đã đọc

- Byte 2: lưu các ký tự đọc

.DATA 

Msg DB 101 
; Đọc tối đa 100 ký tự

DB ?

DB 101 DUP(?)

...

MOV AH,0Ah

LEA DX,Msg

INT 21h
  • Hàm 4Ch: kết thúc chương trình

MOV AH,4Ch

INT 21h

Ngắt 10h

  • Xoá màn hình:

- Gọi AX = 02h

- Trả về: không có

MOV AX,02h 

INT 10h
  • Chuyển toạ độ con trỏ:
  • Gọi AH = 02h, DH = dòng, DL = cột

MOV AH,02h 

MOV DX,0F15h 

INT 10h

Trong lập trình, một vấn đề ta cần quan tâm là truyền tham số giữa chương trình chính và chương trình con. Để thực hiện truyền tham số, ta có thể dùng các cách sau đây:

- Truyền tham số qua thanh ghi

- Truyền tham số qua ô nhớ (biến)

- Truyền tham số qua ô nhớ do thanh ghi chỉ đến

- Truyền tham số qua stack

Truyền tham số qua thanh ghi

Ta thực hiện truyền tham số qua thanh ghi bằng cách: một chương trình con sẽ đưa giá trị vào thanh ghi và chưong trình con khác sẽ xử lý giá trị trên thanh ghi đó.

Cộng giá trị tại 2 ô nhớ 1000h và 1001h, kết quả chứa trong 1002h (bye cao) và 1003h (byte thấp).

.MODEL SMALL 

.STACK 100h

.CODE

main PROC

MOV AX,@DATA

MOV DS,AX

MOV BYTE PTR DS:[1000h],10h 
; Đưa giá trị vào

MOV BYTE PTR DS:[1001h],0FFh 
; các ô nhớ

CALL Read

CALL Sum

Mov AH,4Ch

INT 21h

main ENDP

Read PROC 
; Đọc dữ liệu vào thanh ghi AX

MOV AH,DS:[1000h]

MOV AL,DS:[1001h]

RET

Read ENDP 
; Xử lý dữ liệu tại thanh ghi AX

Sum PROC

ADD AH,AL

JZ next

MOV DS:[1003h],1

next: MOV DS:[1002h],AH

RET 

Sum ENDP END main 

Truyền tham số qua ô nhớ (biến)

Quá trình truyền tham số cũng giống như trên nhưng thay vì thực hiện thông qua thanh ghi, ta sẽ thực hiện thông qua các ô nhớ.

Cộng giá trị tại 2 ô nhớ m1 và m2, kết quả chứa trong m3 (bye cao) và m4 (byte thấp).

.MODEL SMALL 

.STACK 100h

.DATA

m1 db ?

m2 db ?

m3 db ?

m4 db ?

.CODE

main PROC

MOV AX,@data

MOV DS,AX

MOV m1,10h 
; Đưa giá trị vào

MOV m2,0FFh 
; các ô nhớ

CALL Sum

MOV AH,4Ch

INT 21h

main ENDP

Sum PROC

MOV m4,0

MOV AH,m1

ADD AH,m2

JNC next

MOV m4,1

next: MOV m3,AH

RET 

Sum ENDP END main 

Truyền tham số qua ô nhớ do thanh ghi chỉ đến

Trong cách truyền tham số này, ta dùng các thanh ghi SI, DI, BX để chỉ địa chỉ offset của các tham số còn thanh ghi đoạn mặc định là DS.

Cộng giá trị tại 2 ô nhớ m1 và m2, kết quả chứa trong m3 (bye cao) và m4 (byte thấp).

.MODEL SMALL

.STACK 100h

.DATA

m1 db ?

m2 db ?

m3 db ?

m4 db ?

.CODE

main PROC

MOV AX,@data

MOV DS,AX

LEA SI,m1

LEA DI,m2

LEA BX,m3

MOV [SI],10h 
; Đưa giá trị vào

MOV [DI],0FFh 
; các ô nhớ

CALL Sum

MOV AH,4Ch

INT 21h

main ENDP

Sum PROC

MOV AL,[SI]

ADD AL,[DI]

JZ next

MOV [BX+1],1

next: MOV [BX],AL

RET 

Sum ENDP END main 

Truyền tham số qua stack

Trong phương pháp truyền tham số này, ta dùng stack làm nơi chứa các tham số cần truyền thông qua các tác vụ PUSH và POP.

Cộng giá trị tại 2 ô nhớ m1 và m2, kết quả chứa trong m3 (byte cao) và m4 (byte thấp).

.MODEL SMALL 

.STACK 100h

.DATA

m1 dw ?

m2 dw ?

m3 dw ?

m4 dw ?

.CODE

main PROC

MOV AX,@data

MOV DS,AX

LEA SI,m1

LEA DI,m2

MOV [SI],1234h 
; Đưa giá trị vào

MOV [DI],0FEDCh 
; các ô nhớ

PUSH m1 
; Đưa vào stack

PUSH m2

CALL Sum

POP m3 
; Lấy kết quả đưa vào stack

POP m4

MOV AH,4Ch

INT 21h

main ENDP

Sum PROC

POP DX 
; Lưu lại địa chỉ trả về của lệnh CALL

POP AX 
; Lấy dữ liệu từ stack

POP BX

ADD AX,BX

JNC next

PUSH 1

next: PUSH AX

PUSH DX 
; Trả lại địa chỉ trở về của lệnh CALL

RET 

Sum ENDP END main 

In chuỗi ký tự ra màn hình

.MODEL SMALL 

.STACK 100h

.DATA 

msg DB 'Hello$' .CODE 

main PROC  

MOV AX,@DATA   
; Khởi động thanh ghi DS

MOV DS,AX

MOV AX,02h   
; Xoá màn hình

INT 10h

MOV AH,02h   
; Chuyển toạ độ con trỏ

MOV DX,0C15h   
; đến dòng 12 (0Ch) và cột 21 (15h)

INT 10h

LEA DX,msg   
; Địa chỉ thông điệp

MOV AH,09h

INT 21h    
; In thông điệp ra màn hình

MOV AH,4Ch   
;Kết thúc chương trình

INT 21h

main ENDP

END main 

In chuỗi ký tự ra màn hình tại toạ độ nhập vào

.MODEL SMALL

.STACK 100h

.DATA

msg DB 'Hello$'

msg1 DB 'Nhap vao toa do:$'

Crlf DB 0Dh,0Ah,'$'

Td DB 3

DB ?

DB 3 DUP(?)

.CODE 

main PROC

MOV AX,@DATA

MOV DS,AX 
; Khởi động thanh ghi DS

MOV AX,02h

INT 10h 
; Xóa màn hình

LEA DX,msg1

MOV AH,09h 
; In thông điệp

INT 21h

CALL Nhap 
; Nhập dòng

MOV CL,AL

LEA DX,Crlf 
; Xuống dòng

MOV AH,09h

INT 21h

CALL Nhap 
; Nhập cột

MOV CH,AL

MOV AH,02h 
; Chuyển tọa độ con trỏ

MOV DX,CX

INT 10h

LEA DX,msg

MOV AH,09h
; In ra màn hình

INT 21h

MOV AH,4Ch 
; Kết thúc chương trình

INT 21h

main ENDP

Nhap PROC

MOV AH,0Ah 
; Nhập vào

LEA DX,Td

INT 21h

LEA BX,Td 
; Lấy chữ số hàng chục

MOV AL,DS:[BX+2] 

SUB AL,'0' 
; Chuyển từ dạng ký tự sang dạng số

MOV BL,10

MUL BL 
; Nhân số hàng chục với 10

PUSH AX

LEA BX,Td 
; Lấy chữ số hàng dơn vị

MOV AL,DS:[BX+3] SUB AL,'0' 

POP BX 

ADD AL,BL RET 

Nhap ENDP END main

Cộng 2 số nhị phân dài 5 byte

.MODEL SMALL 

.STACK 100h

.DATA

m1 DB 00h,08h,10h,13h,24h,00h

m2 DB 0FFh,0FCh,0FAh,0F0h,0F1h,00h;

m3 DB 6 DUP(0)

.CODE 

main PROC 

MOV AX,@DATA

MOV DS,AX    
; Khởi động thanh ghi DS

LEA SI,m1

LEA DI,m2

LEA BX,m3

MOV CX,6

XOR AL,AL

next: MOV AL,[SI]

ADC AL,[DI]

MOV [BX],AL

INC BX

INC SI

INC DI

LOOP next

MOV AH,4Ch

INT 21h

main ENDP

END main

Nhập một chuỗi ký tự và chuyển chữ thường thành chữ hoa

.MODEL SMALL 

.STACK 100h

.DATA

m1 DB 81

DB ?

DB 81 DUP(?)

m2 DB 'Chuoi da doi:$' .CODE 

main PROC 

MOV AX,@DATA 

MOV DS,AX

MOV ES,AX

LEA DX,m1

MOV AH,0Ah

INT 21h

LEA SI,m1

ADD SI,2

MOV DI,SI

Next: LODSB

CMP AL,0Dh

JE quit

CMP AL,'a'

JB cont

CMP AL,'z'

JA cont

SUB AL,20h

STOSB

DEC DI

cont: INC DI

JMP next

quit: MOV AL,'$'

STOSB

MOV AX,02h

INT 10h

LEA DX,m2

MOV AH,09h

INT 21h

LEA DX,m1+2

MOV AH,09h

INT 21h

MOV AH,4Ch

INT 21h

main ENDP

END main
0