Bài giảng Lập trình với hợp ngữ - Lê Minh Triết
Phần 1:
Quy trình tạo và chạy chương trình
Bộ hợp dịch ASM có hai trình cơ bản là
TASM.EXE (trình hợp dịch)
TLINK.EXE (trình liên kết)
Ngoài ra ta còn cần một chương trình dùng để soạn thảo để tạo chương trình nguồn.
! Ta có thể dùng bộ chương
trình BorlandC để soạn thảo chương trình nguồn.
á trị ban đầu chưa xác định .CODEMAIN PROC; INITIALIZE DS MOV AX,@DATA MOV DS,AX;PRINT PROMPT USER LEA DX,MSG1 ; lấy thông điệp số 1 MOV AH,9 INT 21H ; xuất nó ra màn hình ;nhập vào một ký tự thường và đổi nó thành ký tự hoa MOV AH,1 ; nhập vào 1 ký tự INT 21H ; cất nó trong AL SUB AL,20H ; đổi thành chữ hoa và cất nó trong AL MOV CHAR, AL ; cất ký tự trong biến CHAR ; xuất ký tự trên dòng tiếp theo LEA DX, MSG2 ; lấy thông điệp thứ 2 MOV AH,9 INT 21H ; xuất chuỗi 2, vì MSG2 0 kết thúc bởi ký tự $ nên tiếp tục xuất ký tự có trong biến CHAR ;dos exit MOV AH,4CH INT 21H ; dos exit MAIN ENDP END MAINYêu cầu nhập 1 ký tự, sau đó thay đổi ký tự đã nhập thành ký tự đi liền trước theo thứ tự ASCII và in ra màn hình3.1 Ví dụ về lệnh nhảyĐể hình dung được lệnh nhảy làm việc như thế nào chúng ta hãy viết chương trình in ra toàn bộ tập các ký tự IBM . .MODEL SMALL .STACK 100H .CODE MAIN PROC MOV AH,2 ; hàm xuất ký tự MOV CX,256 ; số ký tự cần xuất MOV DL,0 ; DL giữ mã ASCII của ký tự NUL PRINT_LOOP : INT 21H ;display character INC DL DEC CX JNZ PRINT_LOOP ;nhảy đến print_loop nếu CX# 0 ;DOS EXIT MOV AH,4CH INT 21H MAIN ENDP END MAINNhảy có dấuSYMBOL DESCRITION CONDITION FOR JUMPSJG/JNLE jump if greater than ZF=0 and SF=OF jump if not less than or equal toJGE/JNL jump if greater than or equal to SF=OF jupm if not less or equal toJL/JNGE jump if less than jump if not greater or equal SFOF JLE/JNG jump if less than or equal ZF=1 or SFOF jump if not greater Lệnh CMP ( Compare)Các lệnh nhảy thường lấy kết qủa của lệnh Compare như là điều kiện. Cú pháp của lệnh CMP là : CMP destination, sourceLệnh này so sánh toán hạng nguồn và toán hạng đích bằng cách tính hiệu Dest - Src. Kết qủa không được cất giữ . Lệnh CMP giống như lệnh SUB, chỉ khác: lệnh CMP toán hạng đích không thay đổi. Hiển thị câu hỏi “Is if after 12 noon (Y/N)? và chờ ta bấm một phím,nếu ta bấm y hay Y thông báo “Good afternoon!”,còn bấm n hay N (hay bất kỳ phím) thông báo “Good morning!”.MODEL SMALL.STACK 100h.DATA TimePrompt DB ‘Is it after 12 noon (Y/N)?$ GoodMorningMsg LABEL BYTE DB 0Dh,0Ah, ‘Good morning!’,0Dh,0Ah,’$’ GoodAfternoonMsg LABEL BYTE DB 0Dh,0Ah, ‘Good afternoon!’,0Dh,0Ah,’$’.CODE Begin: MOV AX, @DATA MOV DS, AX LEA DX,TimePrompt MOV AH, 09h INT 21h MOV AH, 01h ;Nhập một ký tự chứa vào AL INT 21h CMP AL, ‘y’ ; Ký tự đã gõ là y? JZ IsAfternoon ; Đúng, nhảy tới IsAfternoon CMP AL, ‘Y’ ;Ký tự gõ là Y? JNZ IsMorning ;Không nhảy tới IsMorning IsAfternoon: ;Không gõ y hay Y LEA DX,GoodAfternoonMsg JMP DisplayGreetingIsMorning: LEA DX,GoodMorningMsgDisplayGreenting: MOV AH, 09h INT 21h MOV AX,4C00h INT 21hEND BeginDiễn dịch lệnh nhảy có điều kiện Ví dụ trên đây về lệnh CMP cho phép lệnh nhảy sau nó chuyển điều khiển đến nhãn BELOW các lệnh CMP AX,BX JG BELOW có nghĩa là nếu AX>BX thì nhảy đến nhãn BELOW Mặc dù lệnh CMP được thiết kế cho các lệnh nhảy. Nhưng lệnh nhảy có thể đứng trước 1 lệnh khác, chẳng hạn : DEC AX JL THERE có nghĩa là nếu AX trong diễn dịch có dấu 0 tiếp tục lặp MOV AX,BX giả sử thân vòng lặp chứa nhiều lệnh mà nó vượt khỏi 126 bytes trước lệnh JNZ TOP . Có thể giải quyết tình trạng này bằng các lệnh sau : TOP: ; thân vòng lặp DEC CX JNZ BOTTOM ; nếu CX>0 tiếp tục lặp JMP EXIT BOTTOM: JMP TOP EXIT: MOV AX,BX3.12 Cấu trúc rẽ nhánhTrong ngôn ngữ cấp cao cấu trúc rẽ nhánh cho phép một chương trình rẽ nhánh đến những đoạn khác nhau tuỳ thuộc vào các điều kiện . Trong phần này chúng ta sẽ xem xét 3 cấu trúc a. IF-THEN b. IF_THEN_ELSE c. CASE a. IF-THEN Cấu trúc IF-THEN có thể diễn đạt như sau : IF condition is true THEN execute true branch statements END IF Ví dụ : Thay thế giá trị trên AX bằng giá trị tuyết đối của nó IF AX 0 thì đặt 1 vào BX Thuật toán : CASE AX 0 put 1 in BX Có thể mã hoá như sau : ; case AX CMP AX,0 ;test AX JL NEGATIVE ;AX0 NEGATIVE: MOV BX,-1 JMP END_CASEZERO: MOV BX,0 JMP END_CASEPOSITIVE: MOV BX,1 JMP END_CASE END_CASE :Rẽ nhánh với tổ hợp các điều kiệnĐôi khi tình trạng rẽ nhánh trong các lệnh IF ,CASE cần một tổ hợp các điều kiện dưới dạng :Condition_1 AND Condition_2Condition_1 OR Condition_2Ví dụ về điều kiện AND :Đọc 1 ký tự và nếu là ký tự hoa thì in ra MH. Thuật toán : Read a character ( into AL) IF ( ‘A’=‘A’? JNGE END_IF ;no, exit CMP AL,’Z’ ; char , terminate THEN : MOV DL,AL MOV AH,2 INT 21H JMP END_IF ELSE_: MOV AH,4CH INT 21h END_IF :3.13 Cấu trúc lặp Một vòng lặp gồm nhiều lệnh được lặp lại, số lần lặp phụ thuộc điều kiện. a. Vòng FOR b. Vòng WHILE c. Vòng REPEATa. Vòng FOR Lệnh LOOP có thể dùng để thực hiện vòng FOR. Cú pháp : LOOP destination_label Số đếm cho vòng lặp là thanh ghi CX mà ban đầu nó được gán 1 giá trị nào đó . Khi lệnh LOOP được thực hiện CX sẽ tự động giảm đi 1. Nếu CX chưa bằng 0 thì vòng lặp được thực hiện tiếp tục. Nếu CX=0 lệnh sau lệnh LOOP được thực hiện Dùng lệnh LOOP , vòng FOR có thể thực hiện như sau : ; gán cho cho CX số lần lặp TOP: ; thân của vòng lặp LOOP TOP Ví dụ : Dùng vòng lặp in ra 1 hàng 80 dấu ‘*’ MOV CX,80 ; CX chưá số lần lặp MOV AH,2 ; hàm xuất ký tự MOV DL,’*’ ;DL chưá ký tự ‘*’ TOP: INT 21h ; in dấu ‘*’ LOOP TOP ; lặp 80 lần Lưu ý rằng vòng FOR cũng như lệnh LOOP thực hiện ít nhất là 1 lần. Do đo nếu ban đầu CX=0 thì vòng lặp sẽ thực hiện lặp đến 65535 lần. Để tránh tình trạng này, lệnh JCXZ (Jump if CX is zero) phải được dùng trước vòng lặp. Lệnh JXCZ có cú pháp như sau : JCXZ destination_label Nếu CX=0 điều khiển được chuyển cho destination_label. Các lệnh sau đây sẽ đảm bảo vòng lặp không thực hiện nếu CX=0 JCXZ SKIP TOP : ; thân vòng lặp LOOP TOP SKIP :b. Vòng WHILE Vòng WHILE phụ thuộc vào 1 điều kiện. Nếu điều kiện đúng thì thực hiện vòng WHILE. Vì vậy nếu điều kiện sai thì vòng WHILE không thực hiện gì cả . Ví dụ : Viết đoạn mã đếm số ký tự được nhập vào trên cùng một hàng . MOV DX,0 ; DX để đếm số ký tự MOV AH,1 ;hàm đọc 1 ký tự INT 21h ; đọc ký tự vào AL WHILE_: CMP AL,0DH ; có phải là ký tự CR? JE END_WHILE ; đúng , thoát INC DX ;tăng DX lên 1 INT 21h ; đọc ký tự JMP WHILE_ ; lặp END_WHILE :c. Vòng REPEAT Cấu trúc REPEAT: repeat statements until condition Trong cấu trúc repeat mệnh đề được thi hành đồng thời điều kiện được kiểm tra. Nếu điều kiện đúng thì vòng lặp kết thúc. Ví dụ : Viết đoạn mã đọc vào các ký tự cho đến khi gặp ký tự trống . MOV AH,1 ; đọc ký tự REPEAT: INT 21h ; ký tự trên AL ;until CMP AL,’ ‘ ; AL=‘ ‘? JNE REPEAT Lưu ý: REPEAT tiến hành ít nhất 1 lần, trong khi đó WHILE có thể không tiến hành lần nào nếu từ đầu điều kiện bị sai. 3.14 Lập trình với cấu trúc cấp cao Bài toán : Viết chương trình nhắc người dùng gõ vào một dòng văn bản. Trên 2 dòng tiếp theo in ra ký tự viết hoa đầu tiên và ký tự viết hoa cuối cùng theo thứ tự alphabetical. Nếu người dùng gõ vào một ký tự thường, máy sẽ thông báo ‘No capitals’ Kết qủa chạy chương trình sẽ như sau : Type a line of text : TRUONG DAI HOC SU PHAM First capital = A Last capital = U Để giải bài toán này ta dùng kỹ thuật lập trình TOP-DOWN, nghĩa là chia nhỏ bài toán thành nhiều bài toán con. Có thể chia bài toán thành 3 bài toán con như sau : 1. Xuất 1 chuỗi ký tự ( lời nhắc) 2. Đọc và xử lý 1 dòng văn bản 3. In kết qủa Bước 1: Hiện dấu nhắc . Bước này có thể mã hoá như sau : MOV AH,9 ; hàm xuất chuỗi LEA DX,PRMOPT ;lấy địa chỉ chuỗi vào DX INT 21H ; xuất chuỗi Dấu nhắc có thể mã hoá như sau trong đoạn số liệu . PROMPT DB ‘Type a line of text:’,0DH,0AH,’$’Bước 2 : Đọc và xử lý một dòng văn bản Đọc các ký tự từ bàn phím , tìm ra ký tự đầu và ký tự cuối , nhắc nhở người dùng nếu ký tự gõ vào không phải là ký tự hoa. Có thể biễu diễn bước này bởi thuật toán sau : Read a characterWHILE character is not a carrige return DOIF character is a capital (*) THEN IF character precedes first capital Then first capital= character End_if IF character follows last character Then last character = character End_ifEND_IF Read a characterEND_WHILE Trong đó dòng (*) có nghĩa là điều kiện để ký tự là hoa là điều kiện AND IF ( ‘A’=‘A’? JNGE END_IF ;không phải ký tự hoa thì nhảy đến END_IF CMP AL,’Z’ ; char =; thì ký tự viết hoa đầu tiên = ký tự MOV FIRST,AL ;FIRST=chr.;end_ifCHECK_LAST:; nếu ký tự là sau biến LAST ( giá trị ban đầu là ‘@’: ký tự trước A) CMP AL,LAST ; char > LAST ? JNG END_IF ; =‘A’? JNGE END_IF ;0 phải K.tự hoa, nhảy đến END_IF CMP AL,’Z’ ; char =; thì ký tự viết hoa đầu tiên = ký tự MOV FIRST,AL ; FIRST=character;end_ifCHECK_LAST:; nếu ký tự là sau biến LAST CMP AL,LAST ; char > LAST ? JNG END_IF ; <=;thì ký tự cuối cùng = ký tự MOV LAST, AL ;LAST = character ;end_ifEND_IF :; đọc một ký tự INT 21H ; ký tự trên AL JMP WHILE_ ; lặp END_WHILE:;in kết quả MOV AH,9 ; hàm xuất ký tự; IF không có chữ hoa nào được nhập thì FIRST =‘[‘ CMP FIRST,’[‘ ; FIRST=‘[‘ ? JNE CAPS ; không , in kết qủa ;Then LEA DX,NOCAP_MSG INT 21HCAPS: LEA DX,CAP1_MSG INT 21H LEA DX,CAP2_MSG INT 21H ; end_if; dos exit MOV AH,4CH INT 21hMAIN ENDPEND MAINBài tập1:Viết chương trình nhập vào 1 số (2-8)In ra màn hình ngày trong tuần tương ứngBài tập2:Nhập vào 1 số nguyên n, không dấu (1-10)Tính tổng=1+2+..+N Mul descDesc là thanh ghi bất kỳ, nhân với giá trị trong thanh ghi ALKết quả lưu vào AX
File đính kèm:
- LAP TRINH VOI HOP NGU.ppt