MỚI NHẤT

Chủ Nhật, 18 tháng 5, 2014

[ASSEMBLY] Chia sẻ code một số bài toán

Cuối tuần rảnh rỗi, dở hợp ngữ ra học, sau một hồi mày mò, nghịch nghịch viết được mấy chương trình chia sẻ cho mọi người:
[ASSEMBLY] Chia sẻ code một số bài toán



Máy tính đơn giản


Chương trình thực hiện các phép tính đơn giản như cộng trừ nhân chia. Phạm vi số: 16bit, số nguyên dương:
; ScanNum luu trong BX
ScanNum MACRO
 LOCAL Nhap, KetThuc
 PUSH AX
 MOV BX, 0
 Nhap: 
  MOV AH, 1
  INT 21h
  CMP AL, 13
  JE KetThuc
  PUSH AX
  MOV AX, BX
  MUL ten
  MOV BX, AX
  POP AX
  AND AL, 0fh
  ADD BL, AL
 JMP Nhap
 KetThuc:
 POP AX
ENDM
; Macro in text
PrintText MACRO n
 PUSH AX
 PUSH DX
 MOV DL, n
 OR DL, 30h  ; Chuyen so thanh ma ASCII tuong ung
 MOV AH, 2
 INT 21h
 POP DX
 POP AX
ENDM

; Chuogn tring chinh
.MODEL SMALL
ORG 100H
.DATA
 MSG1 DB "   My calculators", 0Ah, 0Dh, "$"
 MSG2 DB "Input a: $"
 MSG3 DB 0Ah, 0Dh, "Operator: (+, -, *, /): $"
 MSG4 DB 0Ah, 0Dh, "Input b: $"
 MSG5 DB 0Ah, 0Dh, "Result: $"
 num1 DW ?
 num2 DW ?
 oper DB ?
 ten DW 10
.CODE
 MOV AX, @DATA
 MOV DS, AX
 
 MOV AH, 9
 LEA DX, MSG1
 INT 21h
 LEA DX, MSG2
 INT 21h
 ; Nhap so 1
 ScanNum
 MOV num1, BX
 ; Print label
 MOV AH, 9
 LEA DX, MSG3
 INT 21h
 ; Nhap phep tinh
 MOV AH, 1
 INT 21h
 MOV oper, AL
 ; Print label
 MOV AH, 9
 LEA DX, MSG4
 INT 21h
 ; Nhap so 2
 ScanNum
 MOV num2, BX
 
 CMP oper, '+'
 JE PhepCong
 
 CMP oper, '-'
 JE PhepTru
 
 CMP oper, '*'
 JE PhepNhan
 
 JMP PhepChia
 
 PhepCong:
  MOV AX, num1
  MOV BX, num2
  ADD AX, BX
  JMP Exit
 PhepTru:
  MOV AX, num1
  MOV BX, num2
  SUB AX, BX
  JMP Exit
 PhepNhan:
  MOV DX, 0
  MOV AX, num1
  MOV BX, num2
  MUL BX   ; AX = AL * BL
  JMP Exit
 PhepChia:
  MOV DX, 0
  MOV AX, num1
  MOV BX, num2
  DIV BX   ; AX = AL / BL
 Exit:
  ; Print Label
  PUSH AX
  MOV AH, 9
  LEA DX, MSG5
  INT 21h
  POP AX
  ; Print res

 MOV CX, 1   ; Co danh dau
 MOV BX, 10000
 Begin_Print: 
  CMP BX, 0
  JE End_Print ; BX = 0
  
  CMP CX, 0
  JE Calc   ; CX = 0
  
  CMP AX, BX
  JB Skip   ; AX < BX
 Calc:
  MOV CX, 0
  MOV DX, 0
  DIV BX   ; AX = DX AX / BX
  PrintText AL ; In AL nhu 1 ky tu binh thuong
  MOV AX, DX
  
 Skip:    ; Giam BX 10 lan
  PUSH AX
  MOV DX, 0
  MOV AX, BX
  DIV ten
  MOV BX, AX
  POP AX 
 JMP Begin_Print
 
 End_Print:
  RET
 


Tìm ước chung lớn nhất của 2 số


Nhập vào 2 số 16bit rồi in ra UCLN của chúng:
; MACRO
; MACRO khong lam thay doi gia tri cua bien vao, chi thay doi gia tri thanh ghi
Nhan MACRO reg, num
 LOCAL next, continue, exit
 PUSH AX
 PUSH DX
 PUSH CX
 
 MOV AX, reg
 MOV CX, num
 XOR DX, DX
 next:
  CMP CX, 0
  JE exit
  TEST CX, 1b  ; Ky tu cuoi cua AL = 1=> ZF = 0
  JZ continue  ; ZF = 1
  ADD DX, AX
  continue:
   SHL AX, 1
   SHR CX, 1
  JMP next
 exit:
  MOV reg, DX
 
 POP CX
 POP DX
 POP AX
ENDM

; Nhap so, luu vao AX
ScanNum MACRO
 local Nhap, exit
 PUSH BX
 MOV AH, 1
 XOR BX, BX  ; Tuong duong mov bx, 0
 Nhap:
  INT 21h
  CMP AL, 13
  JE exit
  AND AL, 0Fh
  Nhan BX, 10
  ADD BL, AL
  JMP Nhap
 exit:
  MOV AX, BX
 POP BX
ENDM

; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

; In so co 1 chu so
PrintNum MACRO reg
 PUSH AX
 PUSH DX
 MOV DL, reg
 MOV AH, 2
 OR DL, 30h
 INT 21h
 POP DX
 POP AX
ENDM

; Tim uoc chung lon nhat, xuat ket qua vao DX
UCLN MACRO m, n
 PUSH AX
 PUSH BX
 
 MOV AX, m
 MOV BX, n
 next:
  CMP AX, BX
  JE exit
  JB less
  SUB AX, BX
  JMP next
 less:
  SUB BX, AX
  JMP next
 exit:
  MOV DX, AX
  
 POP BX
 POP AX
ENDM

; Chuong trinh chinh
.MODEL small
ORG 100h
.DATA
 Enter DB 0Dh, 0Ah, '$'
 num1 DW ?
 num2 DW ?
.CODE
 MOV AX, seg Enter
 MOV DS, AX
 
 ScanNum  ; Xuat ra AL
 MOV num1, AX
 
 PUSH AX
 MOV AH, 9
 LEA DX, Enter
 INT 21h
 POP AX 
 
 ScanNum 
 MOV num2, AX
 
 
 PUSH AX
 MOV AH, 9
 LEA DX, Enter
 INT 21h
 POP AX 
 
 XOR DX, DX
 UCLN num1, num2
 MOV AX, DX
 PrintNums 

Chương trình in ra n số hạng đầu tiên trong dãy Fibonacy


Nhập vào 1 số n (từ 1~22) rồi in ra n số hạng đầu tiên trong dãy Fibonacy
; MACRO
; MACRO khong lam thay doi gia tri cua bien vao, chi thay doi gia tri thanh ghi
Nhan MACRO reg, num
 LOCAL next, continue, exit
 PUSH AX
 PUSH DX
 PUSH CX
 
 MOV AX, reg
 MOV CX, num
 XOR DX, DX
 next:
  CMP CX, 0
  JE exit
  TEST CX, 1b  ; Ky tu cuoi cua AL = 1=> ZF = 0
  JZ continue  ; ZF = 1
  ADD DX, AX
  continue:
   SHL AX, 1
   SHR CX, 1
  JMP next
 exit:
  MOV reg, DX
 
 POP CX
 POP DX
 POP AX
ENDM

; Nhap so, luu vao AX
ScanNum MACRO
 local Nhap, exit
 PUSH BX
 MOV AH, 1
 XOR BX, BX  ; Tuong duong mov bx, 0
 Nhap:
  INT 21h
  CMP AL, 13
  JE exit
  AND AL, 0Fh
  Nhan BX, 10
  ADD BL, AL
  JMP Nhap
 exit:
  MOV AX, BX
 POP BX
ENDM

; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

.MODEL SMALL
ORG 100h
.DATA
 count DB ?
 Enter DB 0Ah, 0Dh, '?'
 ten DW 10
.CODE
 ScanNum
 MOV count, AL
 
 XOR DX, DX
 
 ; In dau Enter
 MOV AH, 2
 MOV DL, 0Ah
 INT 21h
 MOV DL, 0Dh
 INT 21h
 
 CMP count, 1
 JE in1
 CMP count, 2
 JE in11
 
 OR BX, 1
 PUSH BX
 PUSH BX
 ; In ra '1 1'
 MOV DL, '1'
  INT 21h
  MOV DL, ' '
  INT 21h
  MOV DL, '1'
  INT 21h
  
 SUB count, 2
 ; Dung stack de luu mang cac so Fibonacy
 next:
  MOV AH, 2
  MOV DL, ' '
  INT 21h
  MOV BP, SP
  MOV BX, [BP]
  ADD BX, [BP+2]
  PUSH BX
  MOV AX, BX
  PrintNums
  
  PUSH AX
  MOV AL, count
  DEC AL
  CMP AL, 0
  JE exit
  MOV count, AL
  POP AX
 JMP next
  
 JMP exit
 ; In so Fibonacy
 in1:
  MOV DL, '1'
  INT 21h 
  JMP exit 
 ; In 2 so dau trong day
 in11:
  MOV DL, '1'
  INT 21h
  MOV DL, ' '
  INT 21h
  MOV DL, '1'
  INT 21h
 exit:
  

[ASSEMBLY] In một số nguyên dương bất kỳ

Trong lập trình hợp ngữ, nhiều lúc bạn muốn thực hiện phép nhân hoặc chia nhưng kết quả lại lưu ở trong thanh ghi AX, và bạn lúng túng không biết in chúng ra như thế nào?! Trong bài này tôi sẽ hướng dẫn các bạn 2 cách đơn giản để in ra 1 số bất kỳ (số nguyên dương, 16bit) trong AX.
[ASSEMBLY] In một số nguyên dương bất kỳ


Với cùng 1 tư tưởng đó là: chia số muốn in thành các chữ số riêng biệt, rồi in từng chữ số đó như 1 ký tự bình thường

Nhắc lại: lệnh DIV 
Cú pháp DIV reg   ; AX = AX / reg => kết quả phép chia nguyên lưu vào AX, số dư lưu vào DL

Cách 1: Duyệt các chữ số từ hàng đơn vị, lưu chúng vào Stack rồi in ngược lại

Với cách này chúng ta chia số muốn in thành các chữ số, thực hiện từ chữ số hàng đơn vị cho đến các chữ số có trọng số cao hơn. Để thực hiện ta tiến hành dùng lệnh DIV để lấy ra số dư phép chia AX cho 10 - chính là chữ số hàng đơn vị của AX. Chữ số này sẽ được cất trong Stack, trở thành đáy Stack (trong phạm vi của thủ tục này), quá trình này lặp lại đến khi AX bằng 0, chữ số có trọng số cao nhất sẽ là đỉnh stack, sẽ được in ra đầu tiên.
Dùng biến CX để đếm số ký tự trong số, phục vụ cho việc lặp in.
[ASSEMBLY] In một số nguyên dương bất kỳ

Để in ra, ta lần lượt lấy các giá trị trong Stack  rồi in chúng như những ký tự bình thường. Việc in sẽ thực hiện từ chữ số có trọng số cao nhất đến chữ số có trọng số thấp nhất (hàng đơn vị). Số lần in sẽ do CX kiểm soát.

Code cụ thể như sau:
; In 1 so bat ky o AX
PrintNums MACRO
 LOCAL next, exit, print
 PUSH BX   ; Cat cac gia tri vao stack
 PUSH CX 
 PUSH DX
 
 MOV BX, 10  ; So chia
 XOR CX, CX  ; MOV CX, 0
 next:
  CMP AX, 0
  JE exit  ; Neu AX = 0 thi dung lai
  XOR DX, DX ; MOV DX, 0
  DIV BX
  PUSH DX  ; DX la so du cua phep chia
  INC CX  ; Tang CX
  JMP next ; Lap lai
 exit:
  MOV AH, 2
  
 print:
  XOR DL, DL ; MOV DL, 0
  POP DX  
  OR DL, 30h ; Chuyen so thanh ma ASCII tuong ung
  INT 21h
  LOOP print ; Lap den khi nao CX = 0
  
 POP DX 
 POP CX 
 POP BX
ENDM

Cách 2: Duyệt các chữ số từ hàng cao nhất đến hàng đơn vị, in trực tiếp (không dùng Stack)

Cũng dùng phép chia để phân tách số ban đầu thành các chữ só riêng biệt nhưng lần này lấy kết quả để in trực tiếp (không lấy in số dư như cách trên). Việc in sẽ tiến hành từ ký tự có trọng số cao nhất đến hàng đơn vị.
Trong mỗi bước ta chia AX cho BX = 10000, sau đó giảm BX xuống còn 1000, 100, 10, 1 (cũng dùng phép chia để giảm BX). 
Dùng CX để lưu trạng thái, tránh việc in những số 0 ở đầu kết quả.

Code cụ thể như sau:
Print PROC
 MOV CX, 1   ; Co danh dau
 MOV BX, 10000
 Begin_Print: 
  CMP BX, 0
  JE End_Print ; BX = 0
  
  CMP CX, 0
  JE Calc   ; CX = 0
  
  CMP AX, BX
  JB Skip   ; AX < BX
 Calc:
  MOV CX, 0
  MOV DX, 0
  DIV BX   ; AX = DX AX / BX
  PrintText AL ; In AL nhu 1 ky tu binh thuong
  MOV AX, DX
  
 Skip:    ; Giam BX 10 lan
  PUSH AX
  MOV DX, 0
  MOV AX, BX
  DIV ten
  MOV BX, AX
  POP AX 
 JMP Begin_Print
 
 End_Print:
Print ENDP

Phần PrintText
; Macro in text
PrintText MACRO n
 PUSH AX
 PUSH DX
 MOV DL, n
 OR DL, 30h  ; Chuyen so thanh ma ASCII tuong ung
 MOV AH, 2
 INT 21h
 POP DX
 POP AX
ENDM


Chúc bạn thành công!!!

Thứ Sáu, 18 tháng 4, 2014

[ASSEMBLY] Biên dịch mã nguồn Assembly sử dụng Tasm + Tlink và emu8086

I. Biên dịch Assembly bằng Tasm - Turbo ASM

Để chạy được file *.asm ta làm như sau:
Download file Tasm Tlink (trong 1 file nén) tại đây.
B1: Soạn thảo nội dung assembly vào 1 file văn bản thông thường, lưu lại với đuôi (định dạng) .asm
B2: Copy file trên cùng 2 file đã giải nén vào ổ D (cho dễ lấy địa chỉ)
B3: Vào cmd (Nhấn đồng thời phím Window + 'R', gõ 'cmd', Enter), trỏ đến ổ D hoặc 1 nơi nào khác lưu các file được đề cập đến ở trên dùng lệnh 'cd'
B4: Thực hiện biên dịch file .asm sang file object: Gõ 'tasm ' + tên file asm, Enter
B5: Biên dịch, gộp file object thành file .exe: Gõ 'tlink' + tên file object, Enter
Kết quả cho ra 1 file .exe.

Lưu ý: Máy window 64bit mà không chạy được 2 file này thì tham khảo tại đây.

II. Chạy Assembly bằng emu8086

'emu8086' là 1 phần mềm cho phép soạn thảo, biên dịch, chạy chương trình Assembly
Tải về chương trình cài đặt và crack tại đây.
Sau khi tải về tiến hành cài đặt và chạy file 'SND-E8086407-KG.exe' để lấy key crack.

Phần mềm hỗ trợ các chức năng:

  • Soạn thảo mã nguồn assembly với highlight
  • Biên dịch mã nguồn sang file .exe
  • Chạy chương trình theo từng dòng lệnh (step)
  • Hiển thị giá trị của các thanh ghi trong từng step
  • Ngoài ra còn có nhiều thông tin bổ trợ như: code mẫu các chương trình đơn giản, bảng mã ASCII...
Giao diện chương trình:
Giao diện và các phím chức năng cơ bản

Chạy chương tình bằng emu8086