intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Giáo trình Ngôn ngữ lập trình Assembly (dùng trong các trường THCN): Phần 2

Chia sẻ: Minh Vũ | Ngày: | Loại File: PDF | Số trang:51

247
lượt xem
47
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Nối tiếp nội dung phần 1 cuốn giáo trình "Ngôn ngữ lập trình Assembly (dùng trong các trường THCN)", phần 2 giới thiệu tới người học các kiến thức: Liên kết Assembly với ngôn ngữ Pascal, các bài toán lập trình. Phần phụ lục trình bày các ngắt của Bios và DOS. Mời các bạn cùng tham khảo.

Chủ đề:
Lưu

Nội dung Text: Giáo trình Ngôn ngữ lập trình Assembly (dùng trong các trường THCN): Phần 2

  1. Chương 3 LIÊN K Ế T ASSEMBLY V Ớ I N G Ô N N G Ữ PASCAL Có hai cách liên kết giữa ngôn ngữ Pascal và Assembly: Cách 1: Chèn các khối lệnh Assembly vào chương trình được viết bằng ngôn ngữ Pascal - inline Assembly. Đây là phương pháp khá đơn giản và nhanh vì với từ khoa asm và được kết thúc bằng end; chúng ta có thể dễ dàng đưa một khối các lệnh của Assembly vào giữa các dòng lệnh của Pascal. Tuy nhiên phương pháp này có một số hạn chế mà chúng ta sẽ đề cập ở phần sau. Cách 2: Viết tách biệt các module: -bằng ngôn ngữ Pascal, và -bằng Assembly. sau đó tiến hành dịch và liên kết chúng lại với nhau. So với cách Ì, cách này sẽ phức tạp hơn cho nguôi lập trình, song sẽ tránh được những nhược điểm mà cách Ì gặp phải. ì. ASSEMBLY TRONG PASCAL Trong phương pháp này, chúng ta đặt các lệnh Assembly vào các dòng trong chương trình được viết bằng ngôn ngữ Pascal tại nơi nào mà chúng ta thấy cần thiết. Dạng tổng quát của Assembly trong chương trình viết bằng Pascal như sau: asm khối các lệnh Assembly end; Mỗi khi chương trình dịch của Pascal gặp từ khoa asm trong dòng lệnh 75
  2. Assembly thì chương trình dịch sẽ chuyển dòng lệnh Asembler này vào và dịch với việc quy chiếu biến Pascal ra dạng tương ứng cùa Assembly để thực hiện. Chúng ta hãy xem xét cơ chế liên kết theo cách này thông qua một ví dụ đơn giản. Ví dụ : Hãy viết chương trình nhập từ bàn phím một số và cất vào một biến bằng Pascal, sau đó giảm giá trị của biến đó đi Ì bằng Assembly và hiện màn hình bằng Pascal với tên tệp là vidu.pas . PROGRAM baitap uses Crt; var x: integer; BEGIN clrscr; write ( 'Hay vào gia tri cua x: '); read (x); asm mov AX, x; đéc AX; mov X, AX; end; writeln ( 'Két qua cua X la : \x); readln; END. Tiến hành dịch như sau: tpc vidu.pas đánh Pascal gặp từ khoa asm và lúc này biến X của Pascal sẽ được chuyển sang biến tương ứng của Assembly và được đặt vào thanh ghi AX. Nói một cách ngắn gọn là từ khoa asm cho phép chúng ta nhét bất kỳ một dòng lệnh Assembly vào chương trình đang được viết bằng ngôn ngữ Pascal. 76
  3. Cách liên kết này khá đơn giản, song vì thế cũng có một số hạn chế: - Các lệnh của Assembly được "dịch nhờ" qua chương trình dịch của Pascal. - Các lệnh nhảy của Assembly chỉ có thể nhảy đến các nhãn Pascal, có nghĩa là lệnh nhảy chỉ có thể thực hiện từ Assembly ra phần ngôn ngữ Pascal chứ không cho phép theo chiều ngược lại và cũng không cho phép các lệnh nhảy trong lòng phần Assembly - nói một cách ngắn gọn không cho phép đặt nhãn nhảy trong phần Assembly. Ví dụ: ỉ asm jz Thoát đéc CX; end; Thoát: Trường hợp này là cho phép vì nhãn thoát là nhãn Pascal nằm trong phần ngôn ngữ Pascal. asm jz Thoát đéc CX; Thoát: end; Trường hợp này là không cho phép vì nhãn Thoát là nhãn của Asembly nằm trong các phần lệnh Assembly. Lưu ý: Lệnh gọi chương trình con CALL không thể coi là lệnh nhảy, do vậy các toán hạng đi sau lệnh CALL có thể là tên của hàm Pascal hoặc các nhãn Assembly, song nhất thiết không thể là nhãn Pascal. li
  4. l i . VIẾT TÁCH BIỆT NHIÊU MODUL (trên nhiều tệp) RIÊNG LẺ Cũng như sự liên kết giữa ngón ngữ Pascal và Assembly, cách thường dùng trong việc liên kết giữa các chương trình viết bằng ngôn ngữ Pascal và Assembly là viết hoàn toàn tách biệt nhiều modul riêng lẻ trong ngôn ngữ Pascal và Asembly, tiến hành dịch các modul đó theo từng modul một và sau đó liên kết những modul này lại với nhau trước khi cho chạy. Và như vậy chúng ta sẽ có được một tệp thực hiện được (đuôi .exe) bằng cách trộn các tệp được viết bằng ngôn ngữ Pascal và Assembly. Viết tách biệt các modul ra với nhau rất có lợi cho các chương trình có số lượng lệnh Assembly lớn vì trong trương hợp này có thể sử dụng toàn bộ khả năng của chương trình dịch MASM và cho phép chúng ta viết và dịch phần chương trình Assembly của chúng ta trong môi trường thuần túy Assembly chứ không phải "dịch nhờ" bởi từ khoa asm trong Pascal. Không những thế phương pháp này giúp chúng ta tránh được những nhược điểm mà Assembly vấp phải. Tuy vậy để thực hiện được sự liên kết theo cách này, người lập trình cho modul của Assembly phải tuân theo tất cả các vấn đề liên quan đến segment, chuyển đổi thông số, các quy chiếu đến các biến của Pascal, sự bảo tồn các biến, thanh ghi.... 1. Những vấn đề cần giải quyết Sau đây chúng ta tìm hiểu các lệnh điều khiển cần thiết cho sự liên kết giữa Pascal và Assembly: 1.1. Vân đề NEAR, FAR và lệnh điều khiên dịch Turbo Pascal chứa nhiều segment mã lệnh nên nó có thể thâm nhập (gọi) các thủ tục của hàm với NEAR và FAR. NEAR CALL sử dụng để thâm nhập vào các chương trình con nằm trong cùng segment với chương trình gọi nó. FAR CALL sẽ thâm nhập vào các chương trình con ờ bất kỳ nơi nào trong vùng nhớ. Turbo Pascal sẽ tự động chọn cách gọi thích hợp dựa vào khai báo của thủ tục theo quy ước sau: Các chương trình con được khai báo ở phẩn interỷace của Unit luôn là FAR sao cho chúng có thể được gọi từ các Unit khác còn các chương trình 78
  5. con được khai báo trong chương trình chính hoặc ớ phần implementation của Unit sẽ là NEAR. Song vì một lý do nào đó thì chương trình con cũng có thể yêu cầu FAR. Để làm được điều này, chương trình dịch Turbo Pascal có trang bị lệnh điều khiển dịch ị$FỊ (compiler directive). Các chương trình còn được dịch với khai báo |$F+| là FAR, còn {$F-| sẽ quay về quy ước trên. 1.2. Vân đề liên kết thông tin giữa Turbo Pascal với Assembly Có hai vấn đề mấu chốt để liên kết thông tin giữa Turbo Pascal với Asembly. Đó là lệnh điều khiển liên kết ($1) và khai báo PUBLIC, EXTERNAL, EXTRN. - Lệnh điều khiển {$1 tên tệp.OBJỊ báo cho chương trình dịch của Turbo Pascal tìm đến tệp có thể ghép được và tiến hành liên kết tệp đó với chương trình của Pascal (tên tệp bao gồm cả đường dẫn). Chương trình được liên kết bằng các module của Pascal và Asembl cũng là chương trình đa tệp do đó phải thoa mãn các yêu cầu về khai báo nhãn (tên biến, tên hàm...) giữa các module với nhau mà cụ thể là: Trong các module viết bằng Assembly phải: - Khai báo PUBLIC trước những nhãn (tên biến toàn cục, tên hàm...) mà các tệp khác cũng sẽ dùng đến bằng cú pháp sau: PUBIC tên nhãn Ì, tên nhãn 2, khai báo nhãn (xác định kích cỡ) Ví dụ: Với tên nhãn là biến nhớ: PUBLIC valuel, value2 valuel DB 10 value2 BW ? Với tên nhãn là tên hàm: PUBIC SUM SUM PROC 79
  6. các lệnh trong thân hàm SUM ENDP - Khai báo EXTRN trước những biến ngoài được tệp này dùng đến với cú pháp sau: EXTRN tên nhãnl : kiểu, tên nhãn! : kiểu... Ví dụ: Với tên nhãn là biến nhớ : EXTRN xi : BYTE, x2 : WORD Với tên nhãn là tên hàm : EXTRN f l : PROC Trong module viết băng ngôn ngữ Pascal phải: - Khai báo external đối với các nhãn ngoài được module này dùng đến với cú pháp sau: tên nhãnl, tên nhãn2,.... : kiểu; external; (đối vối biến) íuntion tên_hàm: kiểu; external; (đối với hàm) procedure tên_thủ_tục; external; (đối với thủ tục) - Việc khai báo PUBIC là không cần thiết. Để có thể dùng chung các biến giữa các module của Pascal và Assembly khi liên kết với nhau, ngoài phần khai báo PUBIC và EXTERNAL, chúng ta cũng nên lưu ý đến sự tương thích về kiểu khai báo dữ liệu theo bảng sau : Kiểu khai báo Kiểu khai báo dữ dữ liệu trong Pascal liệu trong Assembly byte BYTE word WORD shortint BYTE integer WORD real FWORD single DOWRD double QWORD extended TBYTE 80
  7. comp QWORD pointer DWORD Để phần nào minh họa cho những vấn đề trên, chúng ta hãy xem xét ví dụ đơn giản sau: Tính tổng của dãy số nguyên dương khi cho biết số đầu tiên và số lượng số cần tính. 2. Các biến dùng chung được khai báo toàn cục Trong phương pháp này, các biến được dùng chung trong các module của Pascal và Assembly phải được khai báo là biến ngoài, có nghĩa là trong module của Pascal các biến này được khai báo ngoài tất cả các hàm và trong module của Assembly chúng được khai báo trong DATA segment. Chúng ta thấy rõ điều này qua ví dụ trước trong việc tính, trong đó hai biến soluong (được khai báo là biến ngoài trong .DATA segment của module Assembly). Ví dụ: Hãy viết chương trình tính trung bình cộng hai số nguyên với sự phân công sau: Module Pascal thực hiện các nhiệm vụ sau: - Nhận hai số nguyên từ bàn phím, - Gọi chương trình con tính trung bình cộng do Assembly viết, - Hiện giá trị trung bình cộng ra màn hình. Module Assembly: Chương trình con tính trung bình cộng hai số nguyên. Để thể hiện cơ chế chuyển giao tham số khác nhau giữa chương trình gọi (Pascal) và chương trình con (Assembly), ở bài tập này chúng ta sẽ viết chương trình theo ba cách: Bài giải: Ba tham số {soi, soi, và flag) đều chuyển giao thông qua việc khai báo biến toàn cục (khai báo PUBLIC và EXTERNAL). Tên hàm Assembly sẽ mang giá trị phần nguyên (làm tròn dưới) của trung bình cộng. Phần chương trình Pascal: PROGRAM TBC; 81
  8. uses Crt; var soi, so2, flag: integer; ($F+) íunction Average: integer : external; {$L C:\USER\f2.0BJ I ($F+-) BEGIN flag: = 0 clrscr; write ( ' Hay vào so thu nhát: ' ); readln (soi); write ( ' Hay vào so thu hai : ' ); readln (so2); write (' Trung binh cong 2 so nguyên la : ', (0.5*flag + Average): 5:1); readln; END. Phần chương trình con Assembly: .MODELlarge .DATA EXTRN sol:WORD, so2:WORD, flag:WORD .CODE PUBIC Average Average PROC mov AX, soi mov BX, so2 add AX, BX sar AX, Ì jnc LI mov flag, Ì LI: ; Trước khi quay về AX chứa phần nguyên rét ; (làm tròn dưới) của trung bình cộng Average ENDP END 82
  9. Bài tập 1. Hãy viết chương trình nhận một số nguyên từ bàn phím, sau đó tăng lên 1 và hiện số đã tăng ra màn hình, trong đó phần tăng giá trị thực hiện bằng Assembly. Còn phần nhập và hiện ra màn hình được viết bằng Pascal. 2. Hãy viết chương trình so sánh hai số nguyên với sự phản công như sau: Module Pascal thực hiện các nhiệm vụ sau: - Nhập hai số nguyên từ bàn phím, - Gọi chương trình con so sánh hai số do Assembly viết, - Hiện giá trị số bé ra màn hình. Module Assembly: Viết chương trình con so sánh hai số 3. Hãy viết chương trinh tính trung bình cộng hai số nguyên với sự phân công sau: Module Pascal thực hiện các nhiệm vụ sau: - Nhập hai số nguyên từ bàn phím, - Gọi chương trình con tính trung bình cộng do Assembly viết. - Hiện giá trị trung binh cộng ra màn hình. Module Assembly: Viết chương trình con tính trung bình cộng hai số nguyên. 4. Hãy viết chương trình tính n! với n từ 0 - 7 (giới hạn trong 1 thanh ghi 16 bít). Module Pascal thực hiện các nhiệm vụ sau: - Nhập số n từ bàn phím, - Gọi chương trình con tính n! do Assembly viết, - Hiện kết quả giai thừa ra màn hình. Module Assembly: Viết chương trinh con tính giai thừa. 5. Hãy viết chương trình tính tổng dãy số nguyên với sự phân công như sau: Module Pascal thực hiện các nhiệm vụ sau: - Nhập vào số lượng chữ số từ bàn phím, - Hiện các số vừa nhập - Gọi chương trình con tính tổng do Assembly viết, - Hiện giá kết quả tổng ra màn hình. Module Assembly: Viết chương trình con tính tổng số nguyên
  10. Chương 4 C Á C BÀI T O Á N LẬP T R Ì N H ì. CÁC BÀI TOÁN PHẦN SỐ HỌC Bài tập Ì Hãy viết chương trình tính tổng của dãy số tự nhiên khi biết số đầu và số lượng chữ số. Thuật toán cho việc tính tổng của dãy số tự nhiên như sau: Để đơn giản ta ấn định số đầu là Ì và số lượng chữ số là lo 1. Khai báo số đầu, số lượng số tự nhiên và tổng số 2. Nạp số lượng số tự nhiên cần tính tổng vào c x 3. Nạp số đầu tiên vào thanh ghi AX 4. Tổng = AX 5. Giảm số lần lặp sau mỗi lần tính tổng 6. Tăng số tự nhiên tiếp theo 7. Cộng số đó vào tổng 8. Lặp lại từ đầu cho đến khi hết số tự nhiên cần tính Bài giải: .MODEL small -STACK 100 h .DATA so_dau DW Ì so_luong DW 10 84
  11. TONG DW .CODE Programl: mov AX,@data ;đưa địa chỉ (phần segment) mov DS,AX ;của vùng dữ liệu vào DS mov cx, so_luong ;đưa số lần lặp vào c x mov AX, so_dau ;AX = giá trị đầu mov TONG, AX ;TONG bằng giá trị số đầu đéc cx ;Trừ số lần lặp đi Ì LÁP: inc AX ;số tự nhiên tiếp theo add TONG.AX ; TONG =AX loop LÁP ;Lặp cho đến khi c x = 0 mov AH,4Ch ;Kết thúc chương trình quay về DOS im 21h END Programl Bài tập 2: Hãy viết chương trình tính giai thừa của 5 (5 !) bằng hai cách: tạo tệp -EXE và .COM Bài giải: ở đây đầu bài yêu cầu tính giai thừa của 5 là số đã được ấn định trước, ta đều biết 51 = 1 x 2 x 3 x 4 x 5 chính là tích của dãy số tự nhiên từ Ì - 5, do đó có chương trình sau: a. Cách viết chương trình để tạo ra tệp dạng .EXE: .MODEL small .STACK lOOh .DATA Tích DW ? so DW ? 85
  12. .CODE Program2: mov AX,@data mov DS,AX ;khởi tạo DS mov Tích, Ì ;Tich=l mov so,2 ;so = 2 mov cx,4 ;SỐ lần dịch cx = 4 LÁP: mov AX.Tich ;AX = Ì mui so ;AX = 1 x 2 mov Tich.AX ;Tich = AX inc so ;so = so + Ì loop LÁP ;Lặp lại đến khi c x = 0 mov AH,4Ch ;Thoát trở về DOS im 21h END Program2 b. Cách viết chương trình để tạo ra tệp .COM: .MODEL Tiny . CODE ORG lOOh Program2: jmp Start Tích DW ? so DW ? Start: mov Tích, Ì mov so,2 mov cx,4 86
  13. LÁP: mov AX,Tich mui so mov Tich,AX inc so loop LÁP int 20h ; trở về DOS chương trình dạng .COM END Program2 Bài tập 3: Hãy viết chương trình thực hiện việc nhận từ bàn phím một số nguyên dương nhỏ hơn 65535 (giới hạn của 16 bít) với quy định kết thúc việc vào một số bằng cách ấn phím ENTER (mã ASCII là Od h). Thuật toán nhập các số thập phán như sau: Khai báo biến nhớ Khai báo biến nhớ Số = 0 REPEAT Đọc một chữ số ASCII Đổi ký tự ra số nhị phân Số = Số X 10 + giá trị vừa nhập cất Số vào biến UTIL Ký tự nhập là phím ENTER Bài giải: .MODEL small .STACK 100H .DATA SO DW 0 ; sẽ chứa số nhập .CODE , 87
  14. Program3 : mov AX,@data ; Khởi tạo DS mov DS, AX xor cx,cx ; xoa c x = 0 mov BX,0Ah ; cho giá trị BX = 10 LÁP: mov AH,1 ; chờ nhận từ bàn phím 1 ký tự im 21h cmp AL,0Dh ; ký tự vừa nhận là ENTER ? J'E THOÁT ; đúng thoát sub AL,30h ; chuyển số dạng ASCII thành số mov CL,AL ; tạm cất số vừa vào thanh ghi CL mov AX,SO ; lôi giá trị vào trước ra AX mui BX ; nhân với 10 add AX,CX ; cộng giá trị vào trước với số vừa vào mov SO,AX ; cất lại vào biến so jmp LÁP THOÁT: mov AH,4Ch ; trở về DOS im 2lh END Program3 Bài tập 4: Hãy viết chương trình tính tổng đại số của hai số có đấu với số thứ nhất giá trị là lOh, số thứ hai là-2(82h) Bài giải: .MODEL small .STACK lOOh 88
  15. DATA SH1 DB lOh SH2 DB 82h ; số hạng 2 là -2 TONG DB ? .CODE Program4: mov AX,@data mov DS,AX mov BL,SH1 mov BH,BL and BX,807fh ; BH chứa dấu của SH1, BL chứa [SH1] mov CL,SH2 mov CH,CL and cx,807f h ; CH chứa dấu của SH2, CL chứa [SH2] cmp BH,CH ; so sánh dấu hai số jz L2 ; cùng dấu thì nhảy đến L2 mov AL,BL ; trường hợp khác dấu sub AL,CL ; trừ hai giá trị tuyệt đối cho nhau jnc LI xchg BX,CX ; đổi hai sò' cho nhau (cả dấu và giá trị tuyệt đối) LI: sub BL,CL jmp L3 L2 : add BL,CL ; cùng dấu thì cộng hai giá trị tuyệt đối L3: and BL,BL ; xét có phải tổng là 0 jnz L4 ; không phải thì nhảy 89
  16. mov TONG.O ; tổng là 0, tránh trường hợp có dâu - jmp KETTHUC L4: or BL,BH ; gộp dấu vào kết quả tổng mov TONG,BL KETTHUC: mov AH,4Ch ; trờ về DOS int 21h END Program4 Bài tập 5: Hãy viết chương trình con-đưa một số hệ thập phân ra màn hình Thuật toán cho việc đưa ra số thập phân Ì • IF AX
  17. MOV DL,'-' ;Lấy ký tự'-' MOV AH,2 ;Hàm hiện ký tự âm ra màn hình INT 21H ;Indấu'-' POP AX ;lấy lại AX NEG AX ;đổi dấu AX NHAY: ;Lấy ra các chữ số thập phân XOR DX,DX ;CX đếm các chữ số thập phân MOV BX.10D ;BX chứa số chia LÁP: XOR DX,DX ;chuẩn bị word cao cho số bị chia DIV BX ;AX = thương số, DX = số dư PUSH DX ;cất số dư vào ngăn xếp INC cx ;Đếm = Đếm + ỉ OR AX,AX ;Thương số = 0 JNE LÁP ;Không!, tiếp tục MOV AH,2 ;Hàm con in ký tự HIÊN: POP DX ;Chữ số trong DL OR DL,30H ;Đổi nó thành ký tự INT 21H ; In ra màn hình LOOP HIÊN ;Lặp lại cho đến khi xong POP DX ;Phục hồi các thanh ghi POP cx POP BX POP AX RÉT OUTDEC ENDP
  18. l i . BÀI TOÁN VẾ CHUỖI Bài tập 1: Hãy viết chương trình đọc và lưu một chuỗi ký tự Bài giải: DOC_S PROC ;Đọc và lưu một chuỗi ;Vào: DI chứa địa chì offset của chuỗi ;Ra: DI chứa địa chỉ offset của chuối ;BX chứa số ký tự nhập được PUSH AX PUSH DI CLD ;Xử lý từ bên trái sang phải XOR BX,BX ;SỐ ký tự nhập bằng 0 MOV AH, Ì ;Hàm đọc một ký tự INT 21H ;Đọc Ì ký tự vào AL WHILE1: CMP AL, ODH ;Ký tự Enter ? JE END_WHILE1 ;Đúng! Kết thúc ;Nếu ký tự là Backspace CMP AL,08h ;Backspace? JNE ELSE1 ;Không! Lưu nó vào chuỗi ;Thì ĐÉC DI ;Đúng!,lùi con trỏ chuỗi D E C B X ;Giảm bộ đếm số ký tự nhập được JMP READ ;và đọc ký tự khác ELSE1: STOSB ;Lưu ký tự vào chuỗi I N C BX ;Tăng bộ đếm số KT READ: 92
  19. INT 21H ;Đọc ký tự vào AL JMP VVHILEl ;và tiếp tục vòng lặp END_WHILE1: POP DI POP AX RÉT DOC-S ENDP Bài tập 2: Hãy viết chương trình kết hợp hai xâu ký tự lại và hiện ra màn hình (hai xâu ký tự đầu được kết thúc bằng 0). Bài giải: . MODEL small . STACK 200h . DATA Stringl DB 'Hello,',0 String2 DB 'world $',0 String3 DB 50 DUP(?) . CODE Program2: mov AX, @data mov DS, AX cld ; theo chiều tăng của địa chỉ Lea DI, String3 ; ES:DI trỏ đến xâu ký tự gộp mov ES, DI Lea DI,String3 Lea SI, Stringl ; DS:SI trỏ đến Stringl StringlLoop : lodsb ; nạp Ì ký tự của Stringl vào AL 93
  20. and AL, AL ; dựng các cờ jz DoString2 ; 0 thì nhảy (kết thúc Stringl) stosb ; cất Ì ký tự của String Ì vào vị ui xâu jmp StringlLoop DoString2 : mov SI, OFFSET String2; DS:SI trỏ đến String2 String2Loop : lodsb ; nạp Ì ký tự của String2 vào AL stosb ; cất vào vị trí xâu ký tự gộp and AL, AL ; dựng các cờ jnz String2Loop ; chưa bằng 0 thì tiếp tục in mov AH, 9 ; xâu ký tự gộp ra màn hình mov DX, OFFSET String3 int 21h mov AH, 4Ch ; trờ về DOS int 21h END Program2 Bài tập 3: Hãy viết chương trình nhập vào một chuỗi chữ cái hoa, đổi chuỗi đó ra chữ thường và hiện ra với chiều ngược lại, đếm và thông số lượng số chữ b trong chuỗi. Bài giải: .MODEL SMALL .STACK 100H .DATA TB1 DB 'Hay go vào mót chuôi chu cai hoa: ','$' TB2 DB 0Ah,0Dh,'Chuoi da doi thanh chu thuong va xép nguoc: ','$' TB3 DB 0Ah,0Dh,'So chu A: ','$' 94
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2