Một số dạng bài tập ngôn ngữ lập trình Assembly
Trang 2CÁC BÀI TẬP MẪU THUẦN TÚY
HienString M1 ; Hiện thông báo M1 ('Hay vao a : ')
call VAO_SO_N ; Nhận giá trị a
mov bx,ax ; bx = a
HienString M2 ; Hiện thông báo M2 ('Hay vao n : ')
call VAO_SO_N ; Nhận giá trị n
mov cx,ax ; cx = n
HienString crlf ; Quay đầu dòng và xuống hàng
mov ax,bx ; ax=a
call HIEN_SO_N ; Hiện giá trị a lên màn hình
HienString M3 ; Hiện 2 chữ ' luy thua '
mov ax,cx ; ax=n
call HIEN_SO_N ; Hiện giá trị n lên màn hình
HienString M4 ; Hiện chữ ' la : '
Trang 3mov ax,1 ; Gán ax=1
and cx,cx ; Liệu giá trị n (cx=n) có bằng 0 ?
jz HIEN ; Nếu bằng 0 thì nhảy đến nhãn HIEN
LAP: ; còn không thì thực hiện vòng lặp tính a lũy thừa n mul bx ; ax=ax*bx
loop LAP
HIEN:
call HIEN_SO_N ; Hiện giá trị a lũy thừa n (giá trị có trong ax) HienString M5 ; Hiện thông báo M5 ('Co tiep tục CT (c/k) ?' ) mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS) jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình) Exit:
mov ah,4ch ; Về DOS
Trang 4clrscr
HienString M1 ; Hiện thông báo M1 ('Hay vao n : ')
call VAO_SO_N ; Nhận 1 số vào từ bàn phím
mov cx,ax ; cx = n
HienString M2 ; Hiện thông báo M2 ('Giai thua cua ')
call HIEN_SO_N ; Hiện giá trị n
HienString M3 ; Hiện thông báo M3 (' la : ')
mov ax,1 ; ax=1
cmp cx,2 ; Liệu n ≤ 2
jb HIEN ; Đúng là ≤ 2 thì nhảy đến nhãn HIEN
LAP: ; còn không thì thực hiện vòng lặp tính n!
mul cx ; ax=ax*cx
loop LAP
HIEN:
call HIEN_SO_N ; Hiện giá trị n! (có trong ax)
HienString M4 ; Hiện thông báo M4 ('Co tiep tuc CT (c/k) ?') mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS) jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình) Exit:
mov ah,4ch ; Về DOS
Khi chương trình chạy yêu cầu có dang :
Hay vao so thu 1 : -12
Hay vao so thu 2 : 5
Trung binh cong 2 so nguyen la : -3.5
Trang 5M1 db 13,10,'Hay vao so thu 1: $'
M2 db 13,10,'Hay vao so thu 2: $'
M3 db 13,10,'Trung binh cong 2 so nguyen la : $'
HienString M1 ; Hiện thông báo M1 ('Hay vao so thu 1 : ')
call VAO_SO_N ; Nhận giá trị số thứ 1
mov bx,ax ; bx = giá trị số thứ 1
HienString M2 ; Hiện thông báo M2 ('Hay vao so thu 2 : ')
call VAO_SO_N ; Nhận giá trị số thứ 2
HienString M3 ; Hiện thông báo M3 ('Trung binh cong 2 so nguyen la :') add ax,bx ; Tổng 2 số (ax=ax+bx)
and ax,ax ; Giá trị tổng là âm hay dương?
jns L1 ; Tổng là dương thì nhảy đến L1
HienString dautru ; còn âm thì hiện dấu '-'
neg ax ; và đổi dấu số bị chia
L1:
shr ax,1 ; Chia đôi làm tròn dưới
pushf ; Cất giá trị cờ vào stack (thực chất là giá trị cờ Carry)
call HIEN_SO_N ; Hiện giá trị trung bình cộng làm tròn dưới
popf ; Lấy lại giá trị cờ từ stack (lấy lại trạng thái bit cờ Carry)
jnc L2 ; Nếu Carry=0 (giá trị tổng là chẳn) thì nhảy
HienString M4 ; còn Carry # 0 thì hiện thêm '.5' lên màn hình
L2:
HienString M5 ; Hiện thông báo M5 ('Co tiep tuc CT (c/k)? ')
mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS)
jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình)
Exit:
mov ah,4ch ; Về DOS
int 21h
INCLUDE lib2.asm
Trang 6Khi chương trình chạy yêu cầu có dang :
Hay vao so luong thanh phan : 4
a[0] = -10
a[1] = 5
a[2] = -15
a[3] = 8
Day so vua vao la : -10 5 -15 8
Tong day so nguyen la : -12
M6 db 10,13,'Tong day so nguyen la : $'
M7 db 13,10,'Co tiep tuc CT (c/k) ? $'
mov cx,ax ; cx=số lượng thành phần (chỉ số vòng lặp LOOP)
lea bx,a ; bx là con trỏ offset của a[0]
mov i,0 ; Gán giá trị biến nhớ i=0
Trang 7L1:
HienString M2 ; Hiện thông báo M2 ('a[')
mov ax,i ; Hiện giá trị i
call HIEN_SO_N
HienString M3 ; Hiện thông báo M3 ('] =')
call VAO_SO_N ; Nhận các thành phần a[i]
mov [bx],ax ; Đưa giá trị a[i] vào mảng a do bx trỏ đến
inc i ; Tăng giá trị i lên 1
add bx,2 ; bx trỏ đến thành phần tiếp theo của mảng a
loop L1
; Vòng lặp đưa các số của mảng lên màn hình
HienString M4 ; Hiện thông báo M4 ('Day so vua vao la : ')
mov cx,sltp ; cx=số lượng thành phần (chỉ số vòng lặp)
lea bx,a ; bx trỏ đến a[0]
L2:
mov ax,[bx] ; ax=a[i]
call HIEN_SO_N ; Hiện giá trị a[i] lên màn hình
HienString M5 ; Hiện 2 dấu cách (space)
add bx,2 ; bx trỏ đến thành phần tiếp theo của mảng
loop L2
; Vòng lặp tính tổng
HienString M6 ; Hiện thông báo M6 ('Tong day so nguyen la : ')
mov cx,sltp ; cx=số lượng thành phần của mảng (chỉ số vòng lặp)
lea bx,a ; bx trỏ đến a[0] (con trỏ offset)
xor ax,ax ; ax chứa tổng (lúc đầu bằng 0)
; -
; L3: |
; add ax,[bx] ; ax=ax+a[i] |
; add bx,2 ; bx trỏ đến thành phần tiếp theo của mảng a |
; loop L3 |
; - call HIEN_SO_N ; Hiện giá trị tổng
HienString M7 ; Hiện thông báo M7 (Co tiep tuc CT (c/k) ?')
mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS)
jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình)
Exit:
mov ah,4ch ; Về DOS
Trang 8and dx,dx ; Dựng cờ dấu (S=1 thì dx chứa số âm, S=0 thì dx chứa số dương)
js L4 ; Nếu giá trị a[i] âm thì nhảy
add ax,[bx] ; còn giá trị a[i] dương thì cộng vào tổng nằm ở ax
shr dx,1 ; Bit thấp nhất vào cờ Carry (C=1-> a[i] là lẻ, C=0 -> a[i] là chẵn)
jc L4 ; Nếu giá trị a[i] là lẻ thì nhảy đến l4
add ax,[bx] ; còn giá trị a[i] là chẵn thì thì cộng vào tổng nằm ở ax
Trang 9; Chia 2 số với số bị chia là nguyên |
; còn số chia là nguyên dương |
; ( 2 chữ số sau dấu thập phân) |
M1 db 10,13,'Hay vao so bi chia : $'
M2 db 10,13,'Hay vao so chia : $'
HienString M1 ; Hiện thông báo M1 ('Hay vao so bi chia : ')
call VAO_SO_N ; Nhận giá trị số bị chia
mov bx,ax ; bx = số bị chia
HienString M2 ; Hiện thông báo M2 ('Hay vao so chia : ')
call VAO_SO_N ; Nhận giá trị số chia (ax = số chia)
xchg ax,bx ; Đổi chéo (ax=số bị chia, bx=số chia)
HienString M3 ; Hiện thông báo M3 ('Thuong la : ')
and ax,ax ; Dựng cờ dấu của số bị chia (dấu thương cùng dấu số bị chia) jns CHIA1 ; Nếu dấu số bị chia là dương thì nhảy đến nhãn CHIA1
HienString dautru ; còn nếu số bị chia là âm thì hiện dấu '-' lên màn hình (dấu âm)
neg ax ; Đổi dấu số bị chia (để thành số nguyên dương)
CHIA1:
xor dx,dx ; dx = 0
div bx ; dx:ax chia cho bx (ax=thương còn dx=dư)
call HIEN_SO_N ; Hiện giá trị của thương lên màn hình
and dx,dx ; Dựng cờ của phần dư (Z=1 thì dư=0, còn Z=0 thì dư≠0)
jz KT ; Dư bằng 0 thì nhảy đến kết thúc quá trình chia
HienString daucham ; còn không thì hiện dấu chấm ('.') và tiếp tục chia
Trang 10mov cx,2 ; Số chữ số sau dấu thập phân
mov si,10 ; si = 10
CHIA2:
mov ax,dx ; Đưa phần dư vào ax
mul si ; Nhân phần dư cho 10
div bx ; dx:ax chia cho bx
call HIEN_SO_N ; Hiện giá trị của thương lên màn hình
and dx,dx ; Dựng cờ của phần dư (Z=1 thì dư=0, còn Z=0 thì dư≠0)
jz KT ; Phần dư bằng 0 thì nhảy đến kết thúc quá trình chia
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS)
jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình) Exit:
mov ah,4ch ; Về DOS
; Tổng cấp số cộng khi biết n (số lượng thành phần) |
; d (công sai) và u1 (giá trị thành phần đầu tiên) |
M4 db 10,13,' Tong cap so cong la : $'
M5 db 10,13,'Co tiep tuc (c/k) ? $'
.CODE
PS:
mov ax,@data
Trang 11mov ds,ax
CLRSCR ; Xóa màn hình
HienString M1 ; Hiện thông báo M1 ('Hay vao n : ')
call VAO_SO_N ; Nhận giá trị n
mov cx,ax ; cx = n
HienString M2 ; Hiện thông báo M2 ('Hay vao d : ')
call VAO_SO_N ; Nhận giá trị d
mov bx,ax ; bx = d
HienString M3 ; Hiện thông báo M3 ('Hay vao u1 : ')
call VAO_SO_N ; Nhận giá trị u1
mov dx,ax ; dx = ax = u1 (ax = tổng = u1; dx =ui và lúc đầu bằng u1) dec cx ; Giảm cx đi 1 (n-1)
L1:
add dx,bx ; dx = ui
add ax,dx ; ax = tổng
loop L1
HienString M4 ; Hiện thông báo M3 ('Tong cap so cong la : ')
call HIEN_SO_N ; Hiện tổng cấp số cộng
HienString M5 ; Hiện dòng nhắc M4 ('Co tiep tuc CT (c/k) ?')
mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS)
jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình)
; Tổng cấp số nhân khi biết n (số lượng thành phần) |
; q (công bội) và u1 (giá trị thành phần đầu tiên) |
Trang 12M2 db 10,13,'Hay vao q : $'
M3 db 10,13,'Hay vao u1 : $ '
M4 db 10,13,' Tong cap so nhan la : $'
M5 db 10,13,'Co tiep tuc (c/k) ? $'
HienString M1 ; Hiện thông báo M1 ('Hay vao n : ')
call VAO_SO_N ; Nhận giá trị n
mov cx,ax ; cx = n
HienString M2 ; Hiện thông báo M2 ('Hay vao q : ')
call VAO_SO_N ; Nhận giá trị q
mov bx,ax ; bx = q
HienString M3 ; Hiện thông báo M3 ('Hay vao u1 : ')
call VAO_SO_N ; Nhận giá trị u1
mov si,ax ; si = ax = u1 (si = tổng = u1; ax =ui và lúc đầu bằng u1) dec cx ; Giảm cx đi 1 (n-1)
call HIEN_SO_N ; Hiện tổng cấp số nhân
HienString M5 ; Hiện dòng nhắc M4 ('Co tiep tuc CT (c/k) ?') mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS)
jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình) Exit:
mov ah,4ch ; Về DOS
Trang 13HienString M1 ; Hiện thông báo M1 ('Hay vao N : ')
call VAO_SO_N ; Nhận giá trị N
mov cx,ax ; cx = N (chỉ số vòng lặp)
HienString M2 ; Hiện thông báo M2 ('Tong tu 1 den ')
call HIEN_SO_N ; Hiện giá trị N
HienString M3 ; Hiện thông báo M3 (' la : ')
dec cx ; Giảm cx đi 1 (n-1)
L1:
add ax,cx ; ax = ax+cx
loop L1
call HIEN_SO_N ; Hiện giá trị biểu thức
HienString M4 ; Hiện dòng nhắc M4 ('Co tiep tuc CT (c/k) ?') mov ah,1 ; Chờ nhận 1 ký tự từ bàn phím
int 21h
cmp al,'c' ; Ký tự vừa nhận có phải là ký tự 'c' ?
jne Exit ; Nếu không phải thì nhảy đến nhãn Exit (về DOS) jmp PS ; Còn không thì quay về đầu (bắt đầu lại chương trình) Exit:
mov ah,4ch ; Về DOS
int 21h
INCLUDE lib2.asm
END PS
Trang 14LIÊN KẾT NGÔN NGỮ BẬC CAO VỚI ASSEMBLY Bài 1
• Gọi chương trình con tính an do Assembly viết,
• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính an
Cách 1: Hàm Assembly không đối (a và n khai báo biến toàn cục)
cout<<"\nHay vao a : "; cin>>a;
cout<<"\nHay vao n : "; cin>>n;
cout<<"\n"<<a<<" luy thua "<<n<<" la : "<<LT();
Trang 15cout<<"\nHay vao a : "; cin>>a;
cout<<"\nHay vao n : "; cin>>n;
cout<<"\n"<<a<<" luy thua "<<n<<" la : "<<LT(a);
Trang 16cout<<"\nHay vao a : "; cin>>a;
cout<<"\nHay vao n : "; cin>>n;
cout<<"\n"<<a<<" luy thua "<<n<<" la : "<<LT(a,n);
Trang 17• Gọi chương trình con tính n! do Assembly viết,
• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính n!
Cách 1: Hàm Assembly không đối (n khai báo biến toàn cục) Tệp C++:
cout<<"\nHay vao n : "; cin>>n;
cout<<"\nGiai thua cua "<<n<<" la : "<<GT();
Trang 18cout<<"\nHay vao n : "; cin>>n;
cout<<"\nGiai thưa cua "<<n<<" la : "<<GT(n);
Trang 19• Nhận 2 số nguyên,
• Gọi chương trình con tính trung bình cộng do Assembly viết,
• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính trung bình cộng 2 số nguyên Cách 1: Hàm Assembly không đối (so1, so2 và flag khai báo biến toàn cục) Tệp C++:
cout<<"\nHay vao so1 : "; cin>>so1;
cout<<"\nHay vao so2 : "; cin>>so2
cout<<"\nTrung binh cong 2 so nguyen la : "<<AVERAGE()+0.5*flag;
mov ax,_so1 ; ax = so1
mov bx,_so2 ; ax = so2
add ax,bx ; ax = ax + bx (ax = so1 + so2)
sar ax,1 ; ax = chia đôi làm tròn dưới
Trang 20cout<<"\nHay vao so1 : "; cin>>so1;
cout<<"\nHay vao so2 : "; cin>>so2
cout<<"\nTrung binh cong 2 so nguyen la : "<<AVERAGE(so1,so2)+0.5*flag; getch();
add ax,bx ; ax = ax + bx (ax = so1 + so2)
sar ax,1 ; ax = chia đôi làm tròn dưới
Trang 21{
int so1,so2,flag=0;
clrscr();
cout<<"\nHay vao so1 : "; cin>>so1;
cout<<"\nHay vao so2 : "; cin>>so2
cout<<"\nTrung binh cong 2 so nguyen la :
add ax,bx ; ax = ax + bx (ax = so1 + so2)
sar ax,1 ; ax = chia đôi làm tròn dưới
jnc L1 ; Nếu tổng là chẵn (C=0) thì nhảy đến L1
mov cx,1 ; còn không thì biến cờ flag =1
les bx,[BP+10] ; es:[bx] trỏ đến vùng nhớ chứa biến cờ flag
• Nhận các số của dãy số đưa vào một mảng,
• Gọi chương trình con tính tổng các thành phần của mảng do Assembly viết,
• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính tổng các thành phần của mảng
Trang 22Cách 1: Hàm Assembly không đối (n và địa chỉ a[0] khai báo biến toàn cục) Tệp C++:
mov ax,SEG _a ; ax = phần địa chỉ segment của a[0]
mov es,ax ; es = phần địa chỉ segment của a[0]
mov bx,OFSET _a ; bx = phần địa chỉ offset của a[0]
xor ax,ax ; ax = tổng và lúc đầu tổng = 0
L1:
add ax.es:[bx] ; ax = ax + a[i] (do es:[bx] trỏ đến)
add bx,2 ; bx trỏ đến thành phần tiếp theo của mảng a
Trang 23mov cx,[BP+6] ; cx = n (lấy từ stack)
les bx,[BP+8] ; es:[bx] trỏ đến a[0]
xor ax,ax ; ax = tổng lúc đầu tổng = 0
L1:
add ax.es:[bx] ; ax = ax + a[i] (do es:[bx] trỏ đến)
add bx,2 ; bx trỏ đến thành phần tiếp theo của mảng a loop L1
pop BP ; Hồi phục giá trị BP
Trang 24• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính
Cách 1: Hàm Assembly không đối (N khai báo biến toàn cục) Tệp C++:
cout<<"\nHay vao n : "; cin>>N;
cout<<"\nTong tu 1 den "<<N<<" la : "<<TONG();
Trang 25clrscr();
cout<<"\nHay vao N : "; cin>>N;
cout<<"\nTong tu 1 den "<<N<<" la : "<<TONG(N);
; Tổng cấp số cộng khi biết n (số lượng thành phần) |
; d (công sai) và u1 (giá trị thành phần đầu tiên) |
; -
Phân công nhiệm vụ :
− Ngôn ngữ C++ :
• Nhận n,d và u1,
• Gọi chương trình con tính tổng cấp số cộng do Assembly viết,
• Hiện kết quả lên màn hình
− Ngôn ngữ Assembly : Chương trình con tính tổng cấp số cộng Cách 1: Hàm Assembly không đối (n,d và u1 khai báo biến toàn cục) Tệp C++:
#include <iotream.h>
#include <conio.h>
int n,d,u1;
extern int CSC();
Trang 26void main(void)
{
clrscr();
cout<<"\nHay vao n : "; cin>>n;
cout<<"\nHay vao d : "; cin>>d;
cout<<"\nHay vao u1 : "; cin>>u1;
cout<<"\nTong cap so cong la : "<<CSC();
Trang 27cout<<"\nHay vao d : "; cin>>d;
cout<<"\nHay vao u1 : "; cin>>u1;
cout<<"\nTong cap so cong la : "<<CSC(n);
cout<<"\nHay vao n : "; cin>>n;
cout<<"\nHay vao d : "; cin>>d;