Thông báo

Collapse
No announcement yet.

Lập trình ASM cho 8051

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Lập trình ASM cho 8051

    Mình mở topic này với mong muốn các bạn thảo luận về tệp lệnh và thuật giải cho các bài toán cụ thể.

    Mình nghĩ rằng điều đó thực sự là cần thiết với các bạn mới học vi điều khiển qua đó có tư duy thuật toán rất là rõ ràng.

    Do đó, mình yêu cầu ai post trong này cần ghi rõ giải thuật và chú thích lệnh rõ ràng. Vì thực tế lấy một đoạn code rồi post lên thì chẳng có ý nghĩa gì cả.

    Topic này cũng rất là có tác dụng cho các bạn trong các kì thi Kỹ thuật vi xử lý đó. Bản thân mình học 8051 chỉ sơ sơ, không viết nhiều ứng dụng lắm, đặc biệt là bằng 8051 mà chỉ toàn bằng C thôi. Quan trọng là mình biết nếu lập trình một cái thì mình tìm ở đâu, học ở chỗ nào thôi . Trường mình kì này mới dạy 8051 nên phải viết nhiều nhiều để thi nên tiện viết luôn cho các bạn .

    Mình có upload tệp lệnh của bọn Atmel lên đây.
    http://www.tailieuvietnam.net/downlo...tion%20Set.pdf

    Đề nghị anh em không được post spam trong đây. Nếu ai không biết cần đặt câu hỏi cụ thể và người trả lời phải cụ thể, nếu có hình minh họa là tốt nhất. Tránh việc cứ hỏi đi hỏi lại mệt lắm.

    Các bạn dùng Keil C để viết chương trình nhé:
    http://www.tailieuvietnam.net/downlo...ac/C51v805.zip

    Và chíp ban đầu mình và các bạn sử dụng để viết những bài đơn giản là con 89S52.8051 tệp lệnh là giống nhau chọn con nào cũng ok.Con 89S52 có nhiều điểm mạnh như có 3 timer, 256 byte RAM on chip... :
    8051 based Full Static CMOS controller with Three-Level Program
    Memory Lock, 32 I/O lines, 3 Timers/Counters, 8 Interrupts Sources,
    Watchdog Timer, 2 DPTRs, 8K Flash Memory, 256 Bytes On-chip RAM.
    Chúc mọi người thành công.
    517
    Có, tất nhiên rồi. Mình là người mới học 8051.
    93.42%
    483
    Cũng tạm tạm thôi.
    3.48%
    18
    Không, tất cả những cái này mình biết hết rùi và nó chẳng có ích gì cả.
    0.97%
    5
    Ý kiến khác.
    2.13%
    11
    Last edited by ngohaibac; 28-12-2006, 16:55.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

  • #2
    Form chuẩn của chương trình ASM

    Đầu tiên mình xin giới thiệu dạng form của chương trình ASM theo form chuẩn của www.picvietnam.com. Các bạn nên đọc để hiểu rõ mục đích của cách viết nhé. Nếu viết rõ ràng thì sẽ rất là đơn giản khi debug đó bạn ạ.

    http://picvietnam.com/forum/showthread.php?t=5

    Code:
    ;========================================================
    ; Ten chuong trinh	: 
    ; Nguoi thuc hien	: Ngo Hai Bac
    ; Ngay thuc hien	: 28/12/06
    ; Phien ban	: 1.0
    ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
    ;----------------------------------------------------------------
    ; Ngay hoan thanh	: 
    ; Ngay kiem tra	: 
    ; Nguoi kiem tra	: Ngo Hai Bac
    ;----------------------------------------------------------------
    ; Chu thich	: Mo ta cac diem khac nhau cua cac phien ban khac nhau 
    ;		: hoac cac chu thich khac
    ;		: vd, dung che do Power On Reset, PORTB = 00000000
    ;		: hoac, chuong trinh viet cho PIC Tutorial
    ;		: hoac, chuong trinh nay hoan toan mien phi va co the dung cho
    ;		: moi muc dich khac nhau
    ;========================================================;========================================================
    
    		org		000h			; Reset
    		nop
    		ljmp 	Start
    	
    		org 	003h			; Int EX0
    		nop
    		reti
    	
    		org 	00bh		   	; Int Timer0
    		nop
    		reti
    	
    		org		013h			; Int EX1
    		nop 
    		reti
    	
    		org 	01bh			; Int Timer1
    		nop
    		reti
    		
    		org 	023h			; Int Communication
    		nop 
    		reti
    	
    ;====================================================================
    		stack	equ		2fh
    ;====================================================================
    ; 					Main Program
    ;====================================================================
    		org 	4bh
    
    ;  chuong trinh viet o day
    
    ;====================================================================
    ; Cac chuong trinh con viet o day
    ;====================================================================
    
    		end.
    Chúc các bạn thành công.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

    Comment


    • #3
      Nguyên văn bởi ngohaibac Xem bài viết
      Đầu tiên mình xin giới thiệu dạng form của chương trình ASM theo form chuẩn của www.picvietnam.com. Các bạn nên đọc để hiểu rõ mục đích của cách viết nhé. Nếu viết rõ ràng thì sẽ rất là đơn giản khi debug đó bạn ạ.

      http://picvietnam.com/forum/showthread.php?t=5

      Code:
      ;========================================================
      ; Ten chuong trinh	: 
      ; Nguoi thuc hien	: Ngo Hai Bac
      ; Ngay thuc hien	: 28/12/06
      ; Phien ban	: 1.0
      ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
      ;----------------------------------------------------------------
      ; Ngay hoan thanh	: 
      ; Ngay kiem tra	: 
      ; Nguoi kiem tra	: Ngo Hai Bac
      ;----------------------------------------------------------------
      ; Chu thich	: Mo ta cac diem khac nhau cua cac phien ban khac nhau 
      ;		: hoac cac chu thich khac
      ;		: vd, dung che do Power On Reset, PORTB = 00000000
      ;		: hoac, chuong trinh viet cho PIC Tutorial
      ;		: hoac, chuong trinh nay hoan toan mien phi va co the dung cho
      ;		: moi muc dich khac nhau
      ;========================================================;========================================================
      
      		org		000h			; Reset
      		nop
      		ljmp 	Start
      	
      		org 	003h			; Int EX0
      		nop
      		reti
      	
      		org 	00bh		   	; Int Timer0
      		nop
      		reti
      	
      		org		013h			; Int EX1
      		nop 
      		reti
      	
      		org 	01bh			; Int Timer1
      		nop
      		reti
      		
      		org 	023h			; Int Communication
      		nop 
      		reti
      	
      ;====================================================================
      		stack	equ		2fh
      ;====================================================================
      ; 					Main Program
      ;====================================================================
      		org 	4bh
      
      ;  chuong trinh viet o day
      
      ;====================================================================
      ; Cac chuong trinh con viet o day
      ;====================================================================
      
      		end.
      Chúc các bạn thành công.
      hay qua s co mình tham gia với nhé!

      Comment


      • #4
        Chương trình đo dộ rộng xung

        Trước đây mình có làm bào tập về đo độ rộng xung,mình sử dụng thuật toán là sử dụng timer,cho đếm khi có tín hiệu vào,và dừng timer khi kết thúc tín hiệu,mình sử dung 8951,như vậy timer là 16 bit,giá trị mã đếm được là 16bit tương đương với giá trị là 65535us,bạn nào có thuật toán hay hơn không,để có thể đếm được giá trị lớn hơn 16bit!

        Comment


        • #5
          Rất đơn giản, bạn có thể đếm độ rộng xung dài bất kì bằng ngắt:

          + Khi nào timer tràn thì tăng một biến Index nào đó, biến này đếm số lần tràn của Timer

          Do đó thời gian bạn đo sẽ bằng = Index * 65535us + sô giây trong timer.

          Thế là xong :d. Chúc bạn thành công.
          Technical sale at WT Microelectronics S'pore
          Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
          Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

          Comment


          • #6
            Chi tiết về không gian nhớ của 8051 các bạn có thể xem ở đây:
            http://dientuvietnam.net/forums/show...t=1163&page=24

            Các bài viết của mình dưới đây có thể chưa tối ưu, mong sự góp ý của các bạn vê thuật giải cũng như cách viết để cho mình thi tốt trong kì thi tới .

            1/Bài 1: Cộng hai số 5 byte, yêu cầu và cách làm mình đều viết trong chương trình:

            Code:
            ;========================================================
            ; Ten chuong trinh	: Cong 2 so 5 bytes
            ; Nguoi thuc hien	: Ngo Hai Bac
            ; Ngay thuc hien	: 29/12/06
            ; Phien ban	: 1.0
            ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
            ;----------------------------------------------------------------
            ; Ngay hoan thanh	: 29/12/06
            ; Ngay kiem tra	: 
            ; Nguoi kiem tra	: Ngo Hai Bac
            ;----------------------------------------------------------------
            ; Chu thich	: Chuong trinh don gian dung cho thi cu
            ;			Hai so hang deu trong bo nho, ket qua cat vao so hang dau
            ;			Chu y: MSB duoc cat vao o co dia chi nho
            ;			So I: 49 50 51 52 53 54
            ;			So II:   60 61 62 63 64 
            ; O nho 49 dung luu so nho tu phep cong truoc neu co tran
            ;========================================================
            
            		ORG	00h			; Reset
            		NOP
            		LJMP 	Start
            	
            		ORG 	003h			; Int EX0
            		NOP
            		RETI
            	
            		ORG 	0bh		   	; Int Timer0
            		NOP
            		RETI
            	
            		ORG	13h			; Int EX1
            		NOP 
            		RETI
            	
            		ORG 	1bh			; Int Timer1
            		NOP
            		RETI
            		
            		ORG 	23h			; Int Communication
            		NOP 
            		RETI
            	
            ;====================================================================
            		stack	equ		2fh
            ;====================================================================
            ; 					Main Program
            ;====================================================================
            		ORG 	4bh
            
            Start:  	PUSH 	00h
            		PUSH	01h
            		PUSH 	02h			; Cat R0, R1, R2 vao Stack
            
            		MOV 	R0,	#54h
            		MOV	R1,	#64h
            		MOV	R2,	#5
            		CLR 	C			;Xua co nho C
            
            Loop:	CLR		A		 	; Xoa thanh ghi Accumulator
            		MOV	A,	@R0		; A = du lieu co dia chi = R0
            		ADDC	A,	@R1		; A = A + @R1 + C  
            		MOV	@R0,A		; Cat ket qua vao byte so thu nhat
            		DEC	R0		 	; R0 = R0  - 1
            		DEC	R1			; R1 = R1 - 1
            		DJNZ	R2,	Loop	; Giam R2 va kiem tra neu R2 #0 thi nhay ve Loop, 
            							; = 0 thi chay tiep
            				
            		RLC	A			; Quay trai A voi bit C => A = C
            		MOV	@R0,A		; O nho 49h co gia tri = C
            		POP	02h
            		POP	01h
            		POP	00h
            
            		END.
            Mình xin giải thích cách làm:
            2 số 5 byte là:
            Code:
            b5 b4 b3 b2 b1 b0
                a4 a3 a2 a1 a0
            (mõi số là số 1 byte)

            với mỗi cặp tương ứng (bi, ai) thì chúng ta cộng như sau:
            tổng = ai + bi + nhớ từ phép cộng của hàng trước;
            nếu tổng >0xFF thì nhớ sang hàng tiếp theo và bi = tổng - 0xFF
            nếu tổng <0xFF thì gán bi = tổng

            Điều này thực hiện dễ dàng bằng lệnh ADDC, khi có nhớ từ bit 7 thì sẽ set cờ nhớ C, không nhớ thì nó sẽ tự xóa cờ nhớ này. Do đó C như là số nhớ từ phép tính trước.Vì nó tự động xóa hoặc set nên không cần xóa Nên chỉ cần dùng như sau:
            Code:
            ; R0 là địa chỉ của bi
            ; R1 là địa chỉ của ai
            MOV   A, @R0
            ADDC  A, @R1
            MOV   @R0, A
            Như vậy cần thực hiện 5 vòng lặp. Có nhiều cách lặp, mình sử dụng kiểu Do.. While; (trong C);
            Code:
            index = m; // m = const
            Do{
            // Làm việc gì đó
            index -- ;
            } while (index>0)
            Tướng ứng trong ASM:
            Code:
            MOV  R2,#5  ; gán R2 = 5
            
            LOOP:
            
            ; do something
            
                      DJNZ  R2,LOOP  ; Giảm R2, nếu chưa = 0 thì nhảy đến Loop
            DJNZ: Decrease and Jump if Not Equal

            Chi tiết hơn về các lệnh anh em xem trong tệp lệnh nhé. Rảnh thì mình sẽ viết luôn cả code C cho anh em so sánh nhé :d.

            Chúc anh em thành công.
            Last edited by ngohaibac; 30-12-2006, 01:22.
            Technical sale at WT Microelectronics S'pore
            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

            Comment


            • #7
              2/ Chương trình con

              Một chương trình con trong 8051 thực chất là tập hợp các công việc được thực hiện tại một địa chỉ nhất định trong ROM. Trong main khi gọi tới chương trình con thì chương trình sẽ tăng con trỏ PC lên 1, đồng thời cất địa chỉ PC vào stack.Nó sẽ lấy lại giá trị đó khi kết thúc chương trình nhờ lệnh RET (Return).

              Chương trình con dùng các biến vào và ra là các thanh ghi, do đó nó như là kiểu dùng biến toàn cục trong C vậy.

              Sau đây là chương trình đảo dấu n byte trong bộ nhớ:

              Code:
              	 ;========================================================
              ; Ten chuong trinh	: Hoan thien chuong trinh con dao dau n byte trong bo nho
              ; Nguoi thuc hien	: Ngo Hai Bac
              ; Ngay thuc hien	: 29/12/06
              ; Phien ban	: 1.0
              ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
              ;----------------------------------------------------------------
              ; Ngay hoan thanh	: 29/12/06
              ; Ngay kiem tra	: 
              ; Nguoi kiem tra	: Ngo Hai Bac
              ;----------------------------------------------------------------
              ; Chu thich	: Chuong trinh don gian dung cho thi cu
              ;			Dao dau n byte trong bo nho có địa chỉ <256
              ;			
              ;			Input: R0: dia chi dau
              ;				   R1: dia chi cuoi
              ;			Thuc hien: dao dau tung byte mot
              ;			
              ;========================================================
              Swap_signed:
              			PUSH	02H			
              
              			MOV		02H,	R1   ; R2 = R1
              			DEC		R2	 	; R2 = R2 -1
              			   	
              Loop:		    INC		R2		; Tang R2	
              			
              			MOV		A,	@R2	; A = data trong R2
              			CPL		A		; Dao bit cua A
              			INC		A		; Tang A len 1 don vi
              
              			MOV		@R2,A	; Gan lai gia tri vao o nho do
              
              			MOV		A,	R2
              			XRL		A,	R1	 ; A = R1 or R2 => Neu A = 0 thi R1 = R2
              
              			JNZ		Loop               ; nhảy nếu A khác 0
              
              			POP		02H			
              
              		        RET
              Đảo dấu 1 byte bằng cách lấy số bù 2 của nó.

              Chúc bạn thành công.
              Last edited by ngohaibac; 30-12-2006, 17:40.
              Technical sale at WT Microelectronics S'pore
              Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
              Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

              Comment


              • #8
                Vòng lặp For

                Ngẫu hứng viết vài kiểu vòng lặp. Mình suy nghĩ lấy nên k biết có ổn lắm không. Mong các bạn cho ý kiến nhé.

                Sau đây là vòng lặp for trong C và dịch sang ASM.
                Code:
                unsigned char i;
                for(i = n_begin; i< n_end; i++){
                	// do something
                }
                // continue
                Đầu tiên i = n_begin; sau đó thực hiện lệnh trong vòng lặp.
                Thử điều kiện i<n_end, nếu true thì tăng i và tiếp tục.
                Nếu i= n_end rùi thì tiếp tục chạy và làm các công việc sau vòng lặp.

                Code:
                ; Code asm
                		n_begin equ     1
                		n_end	equ	100
                	
                		MOV	R0,	#n_begin
                		MOV	R1,	#n_end
                
                Loop:	    ; Do something here
                		
                		MOV	A,	R0
                		CJNE	A,	R1,	Loop1 ; nếu A không = R1 thì nhảy đến Loop1
                		SJMP	Loop2                   ; A = R1 thì nhảy đến  loop2
                			
                Loop1:	     INC      R0	
                		SJMP	Loop
                Loop2:	; continue
                Nếu bạn thay n<n_end bằng điều kiện khác thì cấu trúc vẫn thế, vẫn jmp đến loop1, chỉ thay đổi điều kiện nhảy thôi.

                Chúc các bạn thành công.
                Technical sale at WT Microelectronics S'pore
                Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                Comment


                • #9
                  Sau đây, mình chỉ upload lên đoạn chương trình thôi chứ không viết cả chương trình, cả chương trình là tập hợp các đoạn lệnh thôi, không có gì cả.

                  Đây là các đoạn lệnh dùng để thi cử mà. Nếu tiện, mình sẽ viết mấy chương trình ứng dụng nạp chip để test hoặc mô phỏng.

                  Đây là chương trình nhân B với số 24 bit.

                  Code:
                  ;========================================================
                  ; Ten chuong trinh	: Nhan B voi so 24 bit
                  ; Nguoi thuc hien	: Ngo Hai Bac
                  ; Ngay thuc hien	: 30/12/06
                  ; Phien ban	: 1.0
                  ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
                  ;----------------------------------------------------------------
                  ; Ngay hoan thanh	: 30/12/06
                  ; Ngay kiem tra	: 
                  ; Nguoi kiem tra	: Ngo Hai Bac
                  ;----------------------------------------------------------------
                  ; Chu thich	: Chuong trinh don gian dung cho thi cu
                  ;			So 24 bit co dia chi A2 - A1 - A0	  (A0 <A1 <A2)
                  ;			Ket qua dc ghi vao dia chi: Z3 - Z2 - Z1 - Z0  (Z0 < Z1 < Z2 <Z3)
                  ;========================================================
                  ; khai bao cac hang so
                  
                  		A0		equ		30h
                  		;... Cac ban tu khai bao nhe.
                  ;=========================================================
                   
                   
                   		MOV	R0,	A0
                  		DEC	R0
                  		MOV	R1,	Z0
                  		MOV	@R1,	#00h	; Xoa o nho Z0
                  		MOV	B,	#15h	; Thi du B = 15h
                  
                  		MOV	R2,	B
                  
                  Loop:	MOV		A,	@R0
                  		MOV	B,	R2
                  		MUL	AB		   	; Nhan B voi Ai
                  		
                  		ADD	A,		@R1	 ;Cong byte thap vao trong o nho Zi
                  		MOV	@R1,	A	 ;Gan lai Zi
                  
                  		INC	R1			; Tang R1
                  
                  		MOV	@R1,	B	 ; Ghi byte cao cua ket qua vao
                  
                  		INC	R0
                  		MOV	A,	R0
                  
                  		CJNE	A,	#A2,Loop ; Neu R0 # A2 thi nhay den Loop
                  
                  		MOV	B, 	R2	 ; Gan lai B
                  Chúc các ban thành công.
                  Technical sale at WT Microelectronics S'pore
                  Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                  Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                  Comment


                  • #10
                    Nguyên văn bởi ngohaibac Xem bài viết
                    Rất đơn giản, bạn có thể đếm độ rộng xung dài bất kì bằng ngắt:

                    + Khi nào timer tràn thì tăng một biến Index nào đó, biến này đếm số lần tràn của Timer

                    Do đó thời gian bạn đo sẽ bằng = Index * 65535us + sô giây trong timer.

                    Thế là xong :d. Chúc bạn thành công.
                    mình cũng suy nghĩ như bạn,nhưng mình đang bị vướng vào phần nhân một số bất kỳ với một số 16 bit, giả dụ như cái index mình có được là số nằm trong dải số 8bit,nếu bạn có thuật toán thì hướng dẫn mình nhé

                    Comment


                    • #11
                      Rất đơn giản, bạn xem bài số 9 của mình viết đó, có thuật toán nhân một số 6bit với số 24 bit.

                      Còn bài của bạn thì cũng tương tự thôi mà. Gán B = số 6 bit đó là ok.

                      Chúc bạn thành công nhé..
                      Technical sale at WT Microelectronics S'pore
                      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                      Comment


                      • #12
                        Tiếp theo là dịch một số n byte 1 vị trí sang trái theo RLC

                        Code:
                        ;========================================================
                        ; Ten chuong trinh	: Dich mot so n byte tu 1 vi tri theo RLC
                        ; Nguoi thuc hien	: Ngo Hai Bac
                        ; Ngay thuc hien	: 30/12/06
                        ; Phien ban	: 1.0
                        ; Mo ta phan cung	: Dung AT89S52 - thach anh 11.0592 MHZ
                        ;----------------------------------------------------------------
                        ; Ngay hoan thanh	: 30/12/06
                        ; Ngay kiem tra	: 
                        ; Nguoi kiem tra	: Ngo Hai Bac
                        ;----------------------------------------------------------------
                        ; Chu thich	:	dich mot so n byte 1 vi tri theo RLC
                        ; 			   R0: dia chi dau
                        ;			   R1: do dai
                        ;			   LSB duoc cat vao o co dia chi nho
                        ;========================================================
                        
                        Rotate_nByte:
                        		PUSH	00
                        		PUSH	01
                        		CLR	C			; Xoa co C
                        
                        Loop:	     MOV     A,	@R0
                        		RLC	A			 ; Quay trai doi voi A
                        		MOV	@R0,A
                        		
                        		INC	R0			; Tang R0
                        
                        		DJNZ	R1,	Loops	; Khi R1 khac 0 thi van chay tiep vong lap
                        
                        		POP	01
                        		POP	00
                        
                        		MOV	A,	@R0
                        		ADDC	A,	#00h	 ; Gan bit cuoi cung trong C vao bit dau tien
                        
                        		RET
                        Đoạn cuối của hàm, mình cộng bit C vào bit đầu của byte đầu của số đó, vì C chính là bit cao nhất của số đã cho.

                        RLC A

                        có nghĩa là : A = b7b6b5b4b3b2b1b0 và C = m
                        thì sau lệnh trên A = b6b5b4b3b2b1b0m và C = b7

                        Ai có thắc mắc về thuật giải của các bài toán thì cho ý kiến nhé.

                        Chúc anh em thành công.
                        Last edited by ngohaibac; 30-12-2006, 22:09.
                        Technical sale at WT Microelectronics S'pore
                        Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                        Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                        Comment


                        • #13
                          Món này hay đấy

                          Ngày xửa ngày xưa thì làm gì có C đâu mà chả phải chiến bằng ASM. Xin gửi lên đây cho các bạn một vài modul cơ bản nhưng ko phải do mình viết đâu nhé. Do các modul này cái nọ gọi cái kia nên tôi ko tách ra như bạn NHB viết được.

                          1. Các modul giao tiếp qua cổng truyền thông UART
                          Code:
                          ;Serial I/O routines using the 8051's built-in UART.
                          ;Almost all of these should use CIN and COUT, so they
                          ;could pretty easily be adapted to other devices which
                          ;could have similar single character I/O routines,
                          ;including the 8051's UART using interrupts and buffers
                          ;in memory.
                          
                          ;Much of this code appears in PAULMON1... see the
                          ;PAULMON1.EQU file for an example of how to use some
                          ;of these routines.
                          
                          
                              ;timer reload calculation
                              ; baud_const = 256 - (crystal / (12 * 16 * baud))
                          				
                          .equ	baud_const, 252	         ;19200 baud w/ 15 MHz
                          ;.equ	 baud_const, 243	 ;4800 baud w/ 12 MHz
                          
                          
                          ;---------------------------------------------------------;
                          ;							  ;
                          ;	       Subroutines for serial I/O		  ;
                          ;							  ;
                          ;---------------------------------------------------------;
                          
                          
                          cin:	jnb	ri, cin
                          	clr	ri
                          	mov	a, sbuf
                          	ret
                          
                          cout:	jnb	ti, cout
                          	clr	ti
                          	mov	sbuf, a
                          	ret
                          
                          newline:push	acc
                          	mov	a, #13
                          	acall	cout
                          	mov	a, #10
                          	acall	cout
                          	pop	acc
                          	ret
                          
                          	;get 2 digit hex number from serial port
                          	; c = set if ESC pressed, clear otherwise
                          	; psw.5 = set if return w/ no input, clear otherwise
                          ghex:
                          ghex8:	clr	psw.5
                          ghex8c:
                          	acall	cin		;get first digit
                          	acall	upper
                          	cjne	a, #27, ghex8f
                          ghex8d: setb	c
                          	clr	a
                          	ret
                          ghex8f: cjne	a, #13, ghex8h
                          	setb	psw.5
                          	clr	c
                          	clr	a
                          	ret
                          ghex8h: mov	r2, a
                          	acall	asc2hex
                          	jc	ghex8c
                          	xch	a, r2		;r2 will hold hex value of 1st digit
                          	acall	cout
                          ghex8j:
                          	acall	cin		;get second digit
                          	acall	upper
                          	cjne	a, #27, ghex8k
                          	sjmp	ghex8d
                          ghex8k: cjne	a, #13, ghex8m
                          	mov	a, r2
                          	clr	c
                          	ret
                          ghex8m: cjne	a, #8, ghex8p
                          ghex8n: acall	cout
                          	sjmp	ghex8c
                          ghex8p: cjne	a, #21, ghex8q
                          	sjmp	ghex8n
                          ghex8q: mov	r3, a
                          	acall	asc2hex
                          	jc	ghex8j
                          	xch	a, r3
                          	acall	cout
                          	mov	a, r2
                          	swap	a
                          	orl	a, r3
                          	clr	c
                          	ret
                          
                          
                          
                          
                          	;carry set if esc pressed
                          	;psw.5 set if return pressed w/ no input
                          ghex16:
                          	mov	r2, #0		;start out with 0
                          	mov	r3, #0
                          	mov	r4, #4		;number of digits left
                          	clr	psw.5
                          
                          ghex16c:
                          	acall	cin
                          	acall	upper
                          	cjne	a, #27, ghex16d
                          	setb	c		;handle esc key
                          	clr	a
                          	mov	dph, a
                          	mov	dpl, a
                          	ret
                          ghex16d:cjne	a, #8, ghex16f
                          	sjmp	ghex16k
                          ghex16f:cjne	a, #127, ghex16g  ;handle backspace
                          ghex16k:cjne	r4, #4, ghex16e   ;have they entered anything yet?
                          	sjmp	ghex16c
                          ghex16e:acall	cout
                          	acall	ghex16y
                          	inc	r4
                          	sjmp	ghex16c
                          ghex16g:cjne	a, #13, ghex16i   ;return key
                          	mov	dph, r3
                          	mov	dpl, r2
                          	cjne	r4, #4, ghex16h
                          	clr	a
                          	mov	dph, a
                          	mov	dpl, a
                          	setb	psw.5
                          ghex16h:clr	c
                          	ret
                          ghex16i:mov	r5, a		  ;keep copy of original keystroke
                          	acall	asc2hex
                          	jc	ghex16c
                          	xch	a, r5
                          	lcall	cout
                          	mov	a, r5
                          	push	acc
                          	acall	ghex16x
                          	pop	acc
                          	add	a, r2
                          	mov	r2, a
                          	clr	a
                          	addc	a, r3
                          	mov	r3, a
                          	djnz	r4, ghex16c
                          	clr	c
                          	mov	dpl, r2
                          	mov	dph, r3
                          	ret
                          
                          ghex16x:  ;multiply r3-r2 by 16 (shift left by 4)
                          	mov	a, r3
                          	swap	a
                          	anl	a, #11110000b
                          	mov	r3, a
                          	mov	a, r2
                          	swap	a
                          	anl	a, #00001111b
                          	orl	a, r3
                          	mov	r3, a
                          	mov	a, r2
                          	swap	a
                          	anl	a, #11110000b
                          	mov	r2, a
                          	ret
                          
                          ghex16y:  ;divide r3-r2 by 16 (shift right by 4)
                          	mov	a, r2
                          	swap	a
                          	anl	a, #00001111b
                          	mov	r2, a
                          	mov	a, r3
                          	swap	a
                          	anl	a, #11110000b
                          	orl	a, r2
                          	mov	r2, a
                          	mov	a, r3
                          	swap	a
                          	anl	a, #00001111b
                          	mov	r3, a
                          	ret
                          
                          
                          asc2hex:	     ;carry set if invalid input
                          	clr	c
                          	push	b
                          	subb	a,#'0'
                          	mov	b,a
                          	subb	a,#10
                          	jc	a2h1
                          	mov	a,b
                          	subb	a,#7
                          	mov	b,a
                          a2h1:	mov	a,b
                          	clr	c
                          	anl	a,#11110000b	 ;just in case
                          	jz	a2h2
                          	setb	c
                          a2h2:	mov	a,b
                          	pop	b
                          	ret
                          
                          
                          phex:
                          phex8:
                          	push	acc
                          	swap	a
                          	anl	a, #15
                          	add	a, #246
                          	jnc	phex_b
                          	add	a, #7
                          phex_b: add	a, #58
                          	acall	cout
                          	pop	acc
                          phex1:	push	acc
                          	anl	a, #15
                          	add	a, #246
                          	jnc	phex_c
                          	add	a, #7
                          phex_c: add	a, #58
                          	acall	cout
                          	pop	acc
                          	ret
                          
                          
                          PHEX16:
                          	PUSH	ACC
                          	MOV	A,DPH
                          	ACALL	PHEX
                          	MOV	A,DPL
                          	ACALL	PHEX
                          	POP	ACC
                          	RET
                          
                          
                          PSTR:		       ;print string @DPTR
                          	PUSH	ACC
                          PSTR1:	CLR	A
                          	MOVC	A,@A+DPTR
                          	JZ	PSTR2
                          	mov	c, acc.7
                          	anl	a, #01111111b
                          	acall	cout
                          	Jc	pstr2
                          	inc	dptr
                          	SJMP	PSTR1					       
                          PSTR2:	POP	ACC
                          	RET    
                          
                          
                          
                          
                          
                          
                          ;first we initialize all the registers we can, setting up
                          ;for serial communication.
                          
                          poweron:
                          
                          	mov	sp, #0x30
                          	clr	psw.3		;set for register bank 0 (init needs it)
                          	clr	psw.4
                          	orl	PCON,#10000000b   ; set double baud rate
                          	MOV	TMOD,#00010001b
                          	MOV	SCON,#01010000b  ; Set Serial for mode 1 &
                          				 ; Enable reception
                          	ORL	TCON,#01010010b  ; Start timer 1 both timer
                          
                          	mov	a, #baud_const
                          	mov	th1, a
                          
                          	setb	ti		;ti is normally set in this program
                          	clr	ri		;ri is normally cleared
                          
                          	;jump to main program from here...
                          
                          
                          
                          pint8u: ;prints the unsigned 8 bit value in Acc in base 10
                                  push    b
                                  push    acc
                                  sjmp    pint8b
                          
                          pint8:  ;prints the signed 8 bit value in Acc in base 10
                                  push    b
                                  push    acc
                                  jnb     acc.7, pint8b
                                  mov     a, #'-'
                                  lcall   cout
                                  pop     acc
                                  push    acc
                                  cpl     a
                                  add     a, #1
                          pint8b: mov     b, #100
                                  div     ab
                                  setb    f0
                                  jz      pint8c
                                  clr     f0
                                  add     a, #'0'
                                  lcall   cout
                          pint8c: mov     a, b
                                  mov     b, #10
                                  div     ab
                                  jnb     f0, pint8d
                                  jz      pint8e
                          pint8d: add     a, #'0'
                                  lcall   cout
                          pint8e: mov     a, b
                                  add     a, #'0'
                                  lcall   cout
                                  pop     acc
                                  pop     b
                                  ret
                          
                          
                          
                          	;print 16 bit unsigned integer in DPTR, using base 10.
                          pint16u:	;warning, destroys r2, r3, r4, r5, psw.5
                          	push	acc
                          	mov	a, r0
                          	push	acc
                          	clr	psw.5
                          	mov	r2, dpl
                          	mov	r3, dph
                          
                          pint16a:mov	r4, #16	;ten-thousands digit
                          	mov	r5, #39
                          	acall	pint16x
                          	jz	pint16b
                          	add	a, #'0'
                          	lcall	cout
                          	setb	psw.5
                          
                          pint16b:mov	r4, #232	;thousands digit
                          	mov	r5, #3
                          	acall	pint16x
                          	jnz	pint16c
                          	jnb	psw.5, pint16d
                          pint16c:add	a, #'0'
                          	lcall	cout
                          	setb	psw.5
                          
                          pint16d:mov	r4, #100	;hundreds digit
                          	mov	r5, #0
                          	acall	pint16x
                          	jnz	pint16e
                          	jnb	psw.5, pint16f
                          pint16e:add	a, #'0'
                          	lcall	cout
                          	setb	psw.5
                          
                          pint16f:mov	a, r2		;tens digit
                          	mov	r3, b
                          	mov	b, #10
                          	div	ab
                          	jnz	pint16g
                          	jnb	psw.5, pint16h
                          pint16g:add	a, #'0'
                          	lcall	cout
                          
                          pint16h:mov	a, b		;and finally the ones digit
                          	mov	b, r3
                          	add	a, #'0'
                          	lcall	cout
                          
                          	pop	acc
                          	mov	r0, a
                          	pop	acc
                          	ret
                          
                          ;ok, it's a cpu hog and a nasty way to divide, but this code
                          ;requires only 21 bytes!  Divides r2-r3 by r4-r5 and leaves
                          ;quotient in r2-r3 and returns remainder in acc.  If Intel
                          ;had made a proper divide, then this would be much easier.
                          
                          pint16x:mov	r0, #0
                          pint16y:inc	r0
                          	clr	c
                          	mov	a, r2
                          	subb	a, r4
                          	mov	r2, a
                          	mov	a, r3
                          	subb	a, r5
                          	mov	r3, a
                          	jnc	pint16y
                          	dec	r0
                          	mov	a, r2
                          	add	a, r4
                          	mov	r2, a
                          	mov	a, r3
                          	addc	a, r5
                          	mov	r3, a
                          	mov	a, r0
                          	ret
                          
                          
                          upper:	;converts the ascii code in Acc to uppercase, if it is lowercase
                          	push	acc 
                          	clr	c
                          	subb	a, #97
                          	jc	upper2		;is it a lowercase character
                          	subb	a, #26
                          	jnc	upper2
                          	pop	acc
                          	add	a, #224	;convert to uppercase
                          	ret
                          upper2: pop	acc		;don't change anything
                          	ret
                          
                          
                          
                          
                          pbin:	mov	r0, #8
                          pbin2:	rlc	a
                          	mov	f0, c
                          	push	acc
                          	mov	a, #'0'
                          	addc	a, #0
                          	lcall	cout
                          	pop	acc
                          	mov	c, f0
                          	djnz	r0, pbin2
                          	rlc	a
                          	ret
                          
                          
                          lenstr: mov	r0, #0	  ;returns length of a string in r0
                          	push	acc
                          lenstr1:clr	a
                          	movc	a,@a+dptr
                          	jz	lenstr2
                          	mov	c,acc.7
                          	inc	r0
                          	Jc	lenstr2
                          	inc	dptr
                          	sjmp	lenstr1					 
                          lenstr2:pop	acc
                          	ret    
                          
                          
                          .equ    str_buf, 0x20           ;16 byte buffer
                          .equ    max_str_len, 19
                          
                          getstr: ;get a string and store in an internal ram buffer
                                  ;  str_buf = beginning of the buffer
                                  ;  max_str_len = max number of char to receive
                                  ;   (buffer must be one larger for null termination)
                          
                                  mov     r0, #str_buf
                          gstrz:  mov     @r0, #0                 ;fill buffer with zeros
                                  inc     r0
                                  cjne    r0, #(str_buf+max_str_len+1), gstrz
                                  mov     r0, #str_buf
                          gstr_in:lcall   cin
                                  lcall   isascii
                                  jnc     gstr_ctrl
                                  cjne    r0, #(str_buf+max_str_len), gstradd
                                  sjmp    gstr_in
                          gstradd:lcall   cout
                                  mov     @r0, a
                                  inc     r0
                                  sjmp    gstr_in
                          gstr_ctrl:
                                  cjne    a, #13, gstrc2          ;carriage return
                                  clr     a
                                  mov     @r0, a
                                  ret
                          gstrc2: cjne    a, #8, gstrc3           ;backspace
                          gstrbk: cjne    r0, #str_buf, gstrbk2
                                  sjmp    gstr_in
                          gstrbk2:mov     a, #8
                                  lcall   cout
                                  mov     a, #' '
                                  lcall   cout
                                  mov     a, #8
                                  lcall   cout
                                  dec     r0
                                  sjmp    gstr_in
                          gstrc3: cjne    a, #127, gstrc4         ;delete
                                  sjmp    gstrbk
                          gstrc4:
                                  sjmp    gstr_in                 ;ignore all others
                          
                          
                          
                          
                          pstrbuf:  ;print the string in the internal ram buffer
                                  mov     r0, #str_buf
                          pstrbuf2:
                                  mov     a, @r0
                                  jz      pstrbuf3
                                  lcall   cout
                                  inc     r0
                                  sjmp    pstrbuf2
                          pstrbuf3:
                                  ret
                          
                          
                          
                          
                          
                                  ;get unsigned integer input to acc
                          gint8u:
                                  mov     r0, #0          ;r0 holds sum so far
                                  mov     r1, #0          ;r1 counts number of characters
                          gi8_in: lcall   cin
                                  mov     r2, a           ;r2 is temp holding space for input char
                                  clr     c
                                  subb    a, #'0'
                                  jc      gi8_ctrl
                                  subb    a, #10
                                  jnc     gi8_ctrl
                                  mov     a, r0
                                  mov     b, #10
                                  mul     ab
                                  xch     a, b
                                  jnz     gi8_in
                                  mov     a, r2
                                  clr     c
                                  subb    a, #'0'
                                  add     a, b
                                  jc      gi8_in
                                  mov     r0, a
                                  mov     a, r2
                                  lcall   cout
                                  inc     r1
                                  sjmp    gi8_in
                          gi8_ctrl:
                                  mov     a, r2
                                  cjne    a, #13, gi8c2
                                  mov     a, r0
                                  ret
                          gi8c2:  cjne    a, #8, gi8c3
                          gi8bk:  cjne    r1, #0, gi8bk2
                                  sjmp    gi8_in
                          gi8bk2: mov     a, #8
                                  lcall   cout
                                  mov     a, #' '
                                  lcall   cout
                                  mov     a, #8
                                  lcall   cout
                                  mov     a, r0
                                  mov     b, #10
                                  div     ab
                                  mov     r0, a
                                  sjmp    gi8_in
                          gi8c3:  cjne    a, #127, gi8c4
                                  sjmp    gi8bk
                          gi8c4:
                                  sjmp    gi8_in
                          
                          
                          
                          isascii:        ;is acc an ascii char, c=1 if yes, c=0 if no
                                  push    acc
                                  cjne    a, #0x7F, isasc2
                                  sjmp    isasc_no
                          isasc2: anl     a, #10000000b
                                  jnz     isasc_no
                                  pop     acc
                                  push    acc
                                  anl     a, #11100000b
                                  jz      isasc_no
                                  setb    c
                                  pop     acc
                                  ret
                          isasc_no:
                                  clr     c
                                  pop     acc
                                  ret
                          2. Các hàm toán học trong 80C51
                          Code:
                          ;*****************************************************************
                          ;*                                                               *
                          ;*                Some Useful Maths Subroutines                  *
                          ;*             for the 8x51 Microcontroller series               *
                          ;*                   Loughborough University                     *
                          ;*        Department of Electronic & Electrical Engineering      *
                          ;*                       Vsn 3.0 WGM 2000                        *
                          ;*                                                               *
                          ;*****************************************************************
                          
                          ; All parameters in Register bank 0, (r0 to r7)
                          ; Bits 21H and 22H reserved
                          
                          ;=================================================================
                          ; subroutine Cr0
                          ; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:     r0 = signed byte
                          ;
                          ; output:    r0 = magnitude
                          ;            Bit 21H = sign (21H is set if r0 is a negative number)
                          ;
                          ; alters:    acc
                          ;=================================================================
                          
                          Cr0:           mov     a, r0           ; read X into accumulator
                                         jb      acc.7, Cr0a     ; X is negative if bit 7 is 1
                                         clr     21H             ; clear sign bit if 'positive'
                                         ret                     ; done
                          
                          Cr0a:          cpl     a               ; X negative, find abs value
                                         inc     a               ; XA = complement(XT)+1
                                         mov     r0, a           ; save magnitude
                                         setb    21H             ; set sign bit if 'negative'
                                         ret
                          
                          
                          ;=================================================================
                          ; subroutine Cr1
                          ; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:     r1 = signed byte
                          ;
                          ; output:    r1 = magnitude
                          ;            Bit 22H = sign (22H is set if r1 is a negative number)
                          ;
                          ; alters:    acc
                          ;=================================================================
                          
                          Cr1:           mov     a, r1           ; read X into accumulator
                                         jb      acc.7, Cr1a     ; X is negative if bit 7 is 1
                                         clr     22H             ; clear sign bit if 'positive'
                                         ret                     ; done
                          
                          Cr1a:          cpl     a               ; X negative, find abs value
                                         inc     a               ; XA = complement(XT)+1
                                         mov     r1, a           ; save magnitude
                                         setb    22H             ; set sign bit if 'negative'
                                         ret
                          
                          
                          ;===================================================================
                          ; subroutine Cr0r1
                          ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:    r1, r0 = signed word
                          ;
                          ; output:   r1, r0 = magnitude
                          ;           Bit 21H = sign (21H is set if negative number)
                          ;
                          ; alters:   acc, C
                          ;===================================================================
                          
                          Cr0r1:         mov     a, r1           ; high byte into accumulator
                                         jb      acc.7, c0a      ; negative if bit 7 is 1
                                         clr     21H             ; clear sign bit if 'positive'
                                         ret                     ; done
                          
                          c0a:           setb    21H             ; set sign flag
                                         mov     a, r0           ; number is negative
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r0, a 
                                         mov     a, r1           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r1, a
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine Cr2r3
                          ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:    r3, r2 = signed word
                          ;
                          ; output:   r3, r2 = magnitude
                          ;           Bit 22H = sign (22H is set if negative number)
                          ;
                          ; alters:   acc, C
                          ;====================================================================
                          
                          Cr2r3:         mov     a, r3           ; read high into accumulator
                                         jb      acc.7, c1a      ; negative if bit 7 is 1
                                         clr     22H             ; clear sign bit if 'positive'
                                         ret                     ; done
                          
                          c1a:           setb    22H             ; set sign flag
                                         mov     a, r2           ; number is negative
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r2, a 
                                         mov     a, r3           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r3, a
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine Cr4r5
                          ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:    r5, r4 = signed word
                          ;
                          ; output:   r5, r4 = magnitude
                          ;           Bit 21H = sign (21H is set if negative number)
                          ;
                          ; alters:   acc, C
                          ;====================================================================
                          
                          Cr4r5:         mov     a, r5           ; read high into accumulator
                                         jb      acc.7, c3a      ; negative if bit 7 is 1
                                         clr     21H             ; clear sign bit if 'positive'
                                         ret                     ; done
                          
                          c3a:           setb    21H             ; set sign flag
                                         mov     a, r4           ; number is negative
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r4, a 
                                         mov     a, r5           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r5, a
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine Cr0r3
                          ; 32-Bit 2's Complement -> magnitude / Sign Bit Conversion
                          ;
                          ; input:    r3, r2, r1, r0 = signed word
                          ;
                          ; output:   r3, r2, r1, r0 = magnitude
                          ;           Bit 21H = sign (21H is set if negative number)
                          ;
                          ; alters:   acc
                          ;====================================================================
                          
                          Cr0r3:         mov     a, r3           ; read high into accumulator
                                         jb      acc.7, c2a      ; negative if bit 7 is 1
                                         clr     21H             ; clear sign flag if 'positive'
                                         ret                     ; done
                          
                          c2a:           setb    21H             ; set sign flag
                                         mov     a, r0           ; number is negative
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r0, a 
                                         mov     a, r1           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r1,a
                                         mov     a, r2           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r2,a
                                         mov     a, r3           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r3, a
                                         ret                     ; done
                          
                          
                          ;==================================================================
                          ; subroutine Mr0
                          ; 8-Bit magnitude / Sign Bit -> 2's Complement Conversion
                          ;
                          ; input:    r0 = magnitude
                          ;           Bits 21H & 22H = sign bits of operands X and Y
                          ;           (set if negative)
                          ;
                          ; output:   r0 = signed byte
                          ;
                          ; alters:   acc
                          ;==================================================================
                          
                          Mr0:           jb      21H, Mr0b       ; test X sign
                                         jb      22H, Mr0a       ; test Y sign
                                         ret
                          
                          Mr0b:          jnb     22H, Mr0a
                                         ret
                          
                          Mr0a:          mov     a, r0           ; if r0 negative, get abs value
                                         cpl     a               ; complement magnitude of X
                                         inc     a               ; r0 = complement(r0)+1
                                         mov     r0, a           ; save in 2's complement
                                         ret                     ; done
                          
                          
                          ;====================================================================
                          ; subroutine Mr0r1
                          ; 16-Bit magnitude / Sign Bit -> 2's Complement Conversion
                          ;
                          ; input:    r1, r0 = magnitude
                          ;           Bits 21H & 22H = sign bits of operands X and Y
                          ;           (set if negative)
                          ;
                          ; output:   r1, r0 = signed word
                          ;
                          ; alters:   acc, C
                          ;====================================================================
                          
                          Mr0r1:         jb      21H, Mr0r1b     ; test X sign
                                         jb      22H, Mr0r1a     ; test Y sign
                                         ret
                          
                          Mr0r1b:        jnb     22H, Mr0r1a
                                         ret
                          
                          Mr0r1a:        mov     a, r0           ; negate number
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r0, a 
                                         mov     a, r1           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r1, a
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine Mr0r3
                          ; 32-Bit magnitude / Sign Bit -> 2's Complement Conversion
                          ;
                          ; input:    r3, r2, r1, r0 = magnitude
                          ;           Bits 21H & 22H = sign bits of operands X and Y
                          ;           (set if negative)
                          ;
                          ; output:   r3, r2, r1, r0 = signed word
                          ;
                          ; alters:   acc, C
                          ;====================================================================
                          
                          Mr0r3:         jb      21H, Mr0r3b     ; test X sign
                                         jb      22H, Mr0r3a     ; test Y sign
                                         ret
                          
                          Mr0r3b:        jnb     22H, Mr0r3a
                                         ret
                          
                          Mr0r3a:        mov     a, r0           ; negate number
                                         cpl     a               ; complement
                                         add     a, #1           ; and add +1
                                         mov     r0, a 
                                         mov     a, r1           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r1, a
                                         mov     a, r2           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r2, a
                                         mov     a, r3           ; get next byte
                                         cpl     a               ; complement
                                         addc    a, #0
                                         mov     r3, a
                                         ret                     ; done
                          
                          
                          ;====================================================================
                          ; subroutine ADD16
                          ; 16-Bit Signed (2's Complement) Addition
                          ;
                          ; input:     r1, r0 = X
                          ;            r3, r2 = Y
                          ;
                          ; output:    r1, r0 = signed sum S = X + Y
                          ;            Carry C is set if the result (S) is out of range
                          ;
                          ; alters:    acc, C, OV
                          ;====================================================================
                          
                          ADD16:         anl    PSW, #0E7H       ; Register Bank 0
                                         mov     a, r0           ; load X low byte into acc
                                         add     a, r2           ; add Y low byte
                                         mov     r0, a           ; put result in Z low byte
                                         mov     a, r1           ; load X high byte into acc
                                         addc    a, r3           ; add Y high byte with carry
                                         mov     r1, a           ; save result in Z high byte
                                         mov     C, OV
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine ADD32
                          ; 32-Bit Signed (2's Complement) Addition
                          ;
                          ; input:     r3, r2, r1, r0 = X
                          ;            r7, r6, r5, r4 = Y
                          ;
                          ; output:    r3, r2, r1, r0 = signed sum S = X + Y
                          ;            Carry C is set if the result (S) is out of range
                          ;
                          ; alters:    acc, C, OV
                          ;====================================================================
                          
                          ADD32:         anl    PSW, #0E7H       ; Register Bank 0
                                         mov     a, r0           ; load X low byte into acc
                                         add     a, r4           ; add Y low byte
                                         mov     r0, a           ; save result
                                         mov     a, r1           ; load X next byte into acc
                                         addc    a, r5           ; add Y next byte with carry
                                         mov     r1, a           ; save result
                                         mov     a, r2           ; load X next byte into acc
                                         addc    a, r6           ; add Y next byte
                                         mov     r2, a           ; save result
                                         mov     a, r3           ; load X high byte into acc
                                         addc    a, r7           ; add Y high byte with carry
                                         mov     r3, a
                                         mov     C, OV
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine SUB16
                          ; 16-Bit Signed (2's Complement) Subtraction
                          ;
                          ; input:     r1, r0 = X
                          ;            r3, r2 = Y
                          ;
                          ; output:    r1, r0 = signed difference D = X - Y
                          ;            Carry C is set if the result (D) is out of range.
                          ;
                          ; alters:    acc, C, OV
                          ;====================================================================
                          
                          SUB16:         anl    PSW, #0E7H       ; Register Bank 0
                                         mov     a, r0           ; load X low byte into acc
                                         clr     C               ; clear carry flag
                                         subb    a, r2           ; subract Y low byte
                                         mov     r0, a           ; put result in Z low byte
                                         mov     a, r1           ; load X high into accumulator
                                         subb    a, r3           ; subtract Y high with borrow
                                         mov     r1, a           ; save result in Z high byte
                                         mov     C, OV
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine SUB32
                          ; 32-Bit Signed (2's Complement) subtraction
                          ;
                          ; input:     r3, r2, r1, r0 = X
                          ;            r7, r6, r5, r4 = Y
                          ;
                          ; output:    r3, r2, r1, r0 = signed difference D = X - Y
                          ;            Carry C is set if the result (D) is out of range.
                          ;
                          ; alters:    acc, C, OV
                          ;====================================================================
                          
                          SUB32:         anl    PSW, #0E7H       ; Register Bank 0
                                         mov     a, r0           ; load X low byte into acc
                                         clr     C               ; clear carry flag
                                         subb    a, r4           ; subract Y low byte
                                         mov     r0, a           ; put result in Z low byte
                                         mov     a, r1           ; repeat with other bytes...
                                         subb    a, r5
                                         mov     r1, a
                                         mov     a, r2
                                         subb    a, r6
                                         mov     r2, a
                                         mov     a, r3
                                         subb    a, r7
                                         mov     r3, a
                                         mov     C, OV           ; set C if external borrow
                                         ret
                          
                          
                          ;==================================================================
                          ; subroutine MUL8
                          ; 8-Bit x 8-Bit to 16-Bit Product Signed Multiply
                          ; 2's Complement format
                          ;
                          ; input:    r0 = multiplicand X
                          ;           r1 = multiplier Y
                          ;
                          ; output:   r1, r0 = product P = X x Y.
                          ;           
                          ; calls:    UMUL8, Cr0, Cr1, Mr0r1
                          ;
                          ; alters:   acc, C, Bits 21H & 22H
                          ;==================================================================
                          
                          MUL8:          anl     PSW, #0E7H      ; Register Bank 0
                                         acall   Cr0             ; 2's comp -> Mag/Sign
                                         acall   Cr1             ; 2's comp -> Mag/Sign
                                         acall   UMUL8
                                         acall   Mr0r1           ; Mag/Sign -> 2's Comp
                                         ret
                          
                          
                          ;==================================================================
                          ; subroutine UMUL8
                          ; 8-Bit x 8-Bit to 16-Bit Product Unsigned Multiply
                          ;
                          ; input:    r0 = multiplicand X
                          ;           r1 = multiplier Y
                          ;
                          ; output:   r1, r0 = product P = X x Y.
                          ;
                          ; alters:   acc
                          ;==================================================================
                          
                          UMUL8:         push    b
                                         mov     a, r0           ; read X and ...
                                         mov     b, r1           ; ... Y
                                         mul     ab              ; multiply X and Y
                                         mov     r1, b           ; save result high ...
                                         mov     r0, a           ; ... and low
                                         pop     b
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine MUL816
                          ; 8-Bit x 16-Bit to 32-Bit Product signed Multiply
                          ; 2's Complement format
                          ;
                          ; input:    r0 = multiplicand X
                          ;           r3, r2 = multiplier Y
                          ;
                          ; output:   r3, r2, r1, r0 = product P = X x Y (r3 = sign extension)
                          ;
                          ; calls:    Cr0, Cr2r3, Mr0r3
                          ;
                          ; alters:   acc, C, Bits 21H & 22H
                          ;====================================================================
                          
                          MUL816:        push    b
                                         anl     PSW, #0E7H      ; Register Bank 0
                                         acall   Cr0             ; 2's comp -> Mag/Sign
                                         acall   Cr2r3           ; 2's comp -> Mag/Sign
                                         mov     a, r0           ; load X low byte into acc
                                         mov     b, r2           ; load Y low byte into B
                                         mul     ab              ; multiply
                                         push    acc             ; stack result low byte
                                         push    b               ; stack result high byte
                                         mov     a, r0           ; load X into acc again
                                         mov     b, r3           ; load Y high byte into B
                                         mul     ab              ; multiply
                                         pop     00H             ; recall X*YL high byte
                                         add     a, r0           ; add X*YL high and X*YH low
                                         mov     r1, a           ; save result
                                         clr     a               ; clear accumulator
                                         addc    a, b            ; a = b + carry flag
                                         mov     r2, a           ; save result
                                         pop     00H             ; get low result
                                         mov     r3, #0
                                         acall   Mr0r3           ; Mag/Sign -> 2's Comp
                                         pop     b
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine MUL16
                          ; 16-Bit x 16-Bit to 32-Bit Product Signed Multiply
                          ; 2's Complement format
                          ;
                          ; input:    r1, r0 = multiplicand X
                          ;           r3, r2 = multiplier Y
                          ;
                          ; output:   r3, r2, r1, r0 = product P = X x Y
                          ;
                          ; calls:    UMUL16, Cr0r1, Cr2r3, Mr0r3
                          ;
                          ; alters:   acc, C, Bits 21H & 22H
                          ;====================================================================
                          
                          MUL16:         anl     PSW, #0E7H      ; Register Bank 0
                                         acall   Cr0r1           ; 2's comp -> Mag/Sign
                                         acall   Cr2r3           ; 2's comp -> Mag/Sign
                                         acall   UMUL16
                                         acall   Mr0r3           ; Mag/Sign -> 2's Comp
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine UMUL16
                          ; 16-Bit x 16-Bit to 32-Bit Product Unsigned Multiply
                          ;
                          ; input:    r1, r0 = multiplicand X
                          ;           r3, r2 = multiplier Y
                          ;
                          ; output:   r3, r2, r1, r0 = product P = X x Y
                          ;
                          ; alters:   acc, C
                          ;====================================================================
                          
                          UMUL16:        push    B
                                         push    dpl
                                         mov     a, r0
                                         mov     b, r2
                                         mul     ab              ; multiply XL x YL
                                         push    acc             ; stack result low byte
                                         push    b               ; stack result high byte
                                         mov     a, r0
                                         mov     b, r3
                                         mul     ab              ; multiply XL x YH
                                         pop     00H
                                         add     a, r0
                                         mov     r0, a
                                         clr     a
                                         addc    a, b
                                         mov     dpl, a
                                         mov     a, r2
                                         mov     b, r1
                                         mul     ab              ; multiply XH x YL
                                         add     a, r0
                                         mov     r0, a
                                         mov     a, dpl
                                         addc    a, b
                                         mov     dpl, a
                                         clr     a
                                         addc    a, #0
                                         push    acc             ; save intermediate carry
                                         mov     a, r3
                                         mov     b, r1
                                         mul     ab              ; multiply XH x YH
                                         add     a, dpl
                                         mov     r2, a
                                         pop     acc             ; retrieve carry
                                         addc    a, b
                                         mov     r3, a
                                         mov     r1, 00H
                                         pop     00H             ; retrieve result low byte
                                         pop     dpl
                                         pop     B
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine MAC16
                          ; 16-Bit x 16-Bit to 32-Bit Product signed Multiply-Accumulate
                          ; 2's Complement format
                          ;
                          ; input:    r1, r0 = multiplicand X
                          ;           r3, r2 = multiplier Y
                          ;           r7, r6, r5, r4 = 32-bit accumulator Ar
                          ;
                          ; output:   r7, r6, r5, r4 = accumulated result Ar =  Ar + (X x Y)
                          ;           r3, r2, r1, r0 = multiply result M = X x Y
                          ;           Carry C set if overflow
                          ;
                          ; calls:    MUL16
                          ;
                          ; alters:   acc, C, Bits 21H & 22H
                          ;====================================================================
                          
                          MAC16:         anl    PSW, #0E7H       ; Register Bank 0
                                         acall  MUL16+3
                                         mov    A, r4
                                         add    A, r0
                                         mov    r4, A
                                         mov    A, r5
                                         addc   A, r1
                                         mov    r5, A
                                         mov    A, r6
                                         addc   A, r2
                                         mov    r6, A
                                         mov    A, r7
                                         addc   A, r3
                                         mov    r7, A
                                         mov    C, OV
                                         ret
                          
                          
                          ;===============================================================
                          ; subroutine DIV8
                          ; 8-Bit / 8-Bit to 8-Bit Quotient & Remainder signed Divide
                          ; 2's Complement Format
                          ;
                          ; input:    r0 = Dividend X
                          ;           r1 = Divisor Y
                          ;
                          ; output:   r0 = quotient Q of division Q = X / Y
                          ;           r1 = remainder 
                          ;           
                          ; calls:    Cr0, Cr1, Mr0
                          ;
                          ; alters:   acc, C, Bits 21H & 22H
                          ;===============================================================
                          
                          DIV8:          anl     PSW, #0E7H      ; Register Bank 0
                                         acall   Cr0             ; 2's comp -> Mag/Sign
                                         acall   Cr1             ; 2's comp -> Mag/Sign
                                         acall   UDIV8
                                         acall   Mr0             ; Mag/Sign -> 2's Comp
                                         ret
                          
                          
                          ;===============================================================
                          ; subroutine UDIV8
                          ; 8-Bit / 8-Bit to 8-Bit Quotient & Remainder Unsigned Divide
                          ;
                          ; input:    r0 = Dividend X
                          ;           r1 = Divisor Y
                          ;
                          ; output:   r0 = quotient Q of division Q = X / Y
                          ;           r1 = remainder 
                          ;           ;
                          ; alters:   acc, C
                          ;===============================================================
                          
                          UDIV8:         push    b
                                         mov     a, r0           ; read X and ...
                                         mov     b, r1           ; ... Y
                                         div     ab              ; divide X and Y
                                         mov     r0, a           ; save result quotient
                                         mov     r1, b           ; save remainder
                                         pop     b
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine DIV16
                          ; 16-Bit / 16-Bit to 16-Bit Quotient & remainder signed Divide
                          ; 2's Complement Format
                          ;
                          ; input:    r1, r0 = Dividend X
                          ;           r3, r2 = Divisor Y
                          ;
                          ; output:   r1, r0 = quotient Q of division Q = X / Y
                          ;           r3, r2 = remainder 
                          ;           Carry C is set if Y = 0, i.e. divide by 0 attempted
                          ;
                          ; calls:    UDIV16, Cr0r1, Cr2r3, Mr0r1
                          ;
                          ; alters:   acc, r4, r5, r6, r7, flags, Bits 21H & 22H
                          ;====================================================================
                          
                          DIV16:         anl     PSW, #0E7H      ; Register Bank 0
                                         mov     a, r3           ; get divisor high byte
                                         orl     a, r2           ; OR with low byte
                                         jnz     div_OK          ; divisor OK if not 0
                                         setb    C               ; else, overflow
                                         ret
                          
                          div_OK:        push    dpl
                                         push    dph
                                         push    b
                                         acall   Cr0r1           ; 2's comp -> Mag/Sign
                                         acall   Cr2r3           ; 2's comp -> Mag/Sign
                                         acall   UDIV16
                                         acall   Mr0r1           ; Mag/Sign -> 2's Comp
                                         clr     C
                                         pop     b
                                         pop     dph
                                         pop     dpl
                                         ret                     ; done
                          
                          
                          ;====================================================================
                          ; subroutine UDIV16
                          ; 16-Bit / 16-Bit to 16-Bit Quotient & Remainder Unsigned Divide
                          ;
                          ; input:    r1, r0 = Dividend X
                          ;           r3, r2 = Divisor Y
                          ;
                          ; output:   r1, r0 = quotient Q of division Q = X / Y
                          ;           r3, r2 = remainder 
                          ;
                          ; alters:   acc, B, dpl, dph, r4, r5, r6, r7, flags
                          ;====================================================================
                          
                          UDIV16:        mov     r7, #0          ; clear partial remainder
                                         mov     r6, #0
                                         mov     B, #16          ; set loop count
                          
                          div_loop:      clr     C               ; clear carry flag
                                         mov     a, r0           ; shift the highest bit of
                                         rlc     a               ; the dividend into...
                                         mov     r0, a
                                         mov     a, r1
                                         rlc     a
                                         mov     r1, a
                                         mov     a, r6           ; ... the lowest bit of the
                                         rlc     a               ; partial remainder
                                         mov     r6, a
                                         mov     a, r7
                                         rlc     a
                                         mov     r7, a
                                         mov     a, r6           ; trial subtract divisor
                                         clr     C               ; from partial remainder
                                         subb    a, r2
                                         mov     dpl, a
                                         mov     a, r7
                                         subb    a, r3
                                         mov     dph, a
                                         cpl     C               ; complement external borrow
                                         jnc     div_1           ; update partial remainder if
                                                                 ; borrow
                                         mov     r7, dph         ; update partial remainder
                                         mov     r6, dpl
                          div_1:         mov     a, r4           ; shift result bit into partial
                                         rlc     a               ; quotient
                                         mov     r4, a
                                         mov     a, r5
                                         rlc     a
                                         mov     r5, a
                                         djnz    B, div_loop
                                         mov     a, r5           ; put quotient in r0, and r1
                                         mov     r1, a
                                         mov     a, r4
                                         mov     r0, a
                                         mov     a, r7           ; get remainder, saved before the
                                         mov     r3, a           ; last subtraction
                                         mov     a, r6
                                         mov     r2, a
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine DIV32
                          ; 32-Bit / 16-Bit to 32-Bit Quotient & remainder signed Divide
                          ; 2's Complement Format
                          ;
                          ; input:    r3, r2, r1, r0 = Dividend X
                          ;           r5, r4 = Divisor Y
                          ;
                          ; output:   r3, r2, r1, r0 = quotient Q of division Q = X / Y
                          ;           r7, r6, r5, r4 = remainder
                          ;           Carry C is set if Y = 0, i.e. divide by 0 attempted
                          ;
                          ; calls:    UDIV32, Cr0r3, Cr4r5, Mr0r3
                          ;
                          ; alters:   acc, flags, Bits 21H & 22H
                          ;====================================================================
                          
                          DIV32:         anl     PSW, #0E7H      ; Register Bank 0
                                         mov     a, r4           ; get divisor high byte
                                         orl     a, r5           ; OR with low byte
                                         jnz     div32_OK        ; divisor OK if not 0
                                         setb    C               ; else, overflow
                                         ret
                          
                          div32_OK:      acall   Cr0r3           ; 2's comp -> Mag/Sign
                                         acall   Cr4r5           ; 2's comp -> Mag/Sign
                                         acall   UDIV32
                                         acall   Mr0r3           ; Mag/Sign -> 2's Comp
                                         clr     C               ; divisor is not 0
                                         ret                     ; done
                          
                          
                          ;====================================================================
                          ; subroutine UDIV32
                          ; 32-Bit / 16-Bit to 32-Bit Quotient & Remainder Unsigned Divide
                          ;
                          ; input:    r3, r2, r1, r0 = Dividend X
                          ;           r5, r4 = Divisor Y
                          ;
                          ; output:   r3, r2, r1, r0 = quotient Q of division Q = X / Y
                          ;           r7, r6, r5, r4 = remainder
                          ;;
                          ; alters:   acc, flags
                          ;====================================================================
                          
                          UDIV32:        push    08              ; Save Register Bank 1
                                         push    09
                                         push    0AH
                                         push    0BH
                                         push    0CH
                                         push    0DH
                                         push    0EH
                                         push    0FH
                                         push    dpl
                                         push    dph
                                         push    B
                                         setb    RS0             ; Select Register Bank 1
                                         mov     r7, #0          ; clear partial remainder
                                         mov     r6, #0
                                         mov     r5, #0          
                                         mov     r4, #0
                                         mov     B, #32          ; set loop count
                          
                          div_lp32:      clr     RS0             ; Select Register Bank 0
                                         clr     C               ; clear carry flag
                                         mov     a, r0           ; shift the highest bit of the
                                         rlc     a               ; dividend into...
                                         mov     r0, a
                                         mov     a, r1
                                         rlc     a
                                         mov     r1, a
                                         mov     a, r2
                                         rlc     a
                                         mov     r2, a
                                         mov     a, r3
                                         rlc     a
                                         mov     r3, a
                                         setb    RS0             ; Select Register Bank 1
                                         mov     a, r4           ; ... the lowest bit of the
                                         rlc     a               ; partial remainder
                                         mov     r4, a
                                         mov     a, r5
                                         rlc     a
                                         mov     r5, a
                                         mov     a, r6
                                         rlc     a
                                         mov     r6, a
                                         mov     a, r7
                                         rlc     a
                                         mov     r7, a
                                         mov     a, r4           ; trial subtract divisor from
                                         clr     C               ; partial remainder
                                         subb    a, 04
                                         mov     dpl, a
                                         mov     a, r5
                                         subb    a, 05
                                         mov     dph, a
                                         mov     a, r6
                                         subb    a, #0
                                         mov     06, a
                                         mov     a, r7
                                         subb    a, #0
                                         mov     07, a
                                         cpl     C               ; complement external borrow
                                         jnc     div_321         ; update partial remainder if
                                                                 ; borrow
                                         mov     r7, 07          ; update partial remainder
                                         mov     r6, 06
                                         mov     r5, dph
                                         mov     r4, dpl
                          div_321:       mov     a, r0           ; shift result bit into partial
                                         rlc     a               ; quotient
                                         mov     r0, a
                                         mov     a, r1
                                         rlc     a
                                         mov     r1, a
                                         mov     a, r2
                                         rlc     a
                                         mov     r2, a
                                         mov     a, r3
                                         rlc     a
                                         mov     r3, a
                                         djnz    B, div_lp32
                          
                                         mov     07, r7          ; put remainder, saved before the
                                         mov     06, r6          ; last subtraction, in bank 0
                                         mov     05, r5
                                         mov     04, r4
                                         mov     03, r3          ; put quotient in bank 0
                                         mov     02, r2
                                         mov     01, r1
                                         mov     00, r0
                                         clr     RS0
                                         pop     B
                                         pop     dph
                                         pop     dpl
                                         pop     0FH             ; Retrieve Register Bank 1
                                         pop     0EH
                                         pop     0DH
                                         pop     0CH
                                         pop     0BH
                                         pop     0AH
                                         pop     09
                                         pop     08
                                         ret
                          
                          
                          ;====================================================================
                          ; subroutine MULDIV
                          ; 16-Bit x 16-Bit to 32-Bit Product Signed Multiply followed by
                          ; 32-Bit / 16-Bit to 32-Bit Quotient & remainder signed Divide
                          ; 2's Complement Format
                          ;
                          ; input:    r1, r0 = multiplicand X
                          ;           r3, r2 = multiplier Y
                          ;           r5, r4 = divisor Z
                          ;
                          ; output:   r3, r2, r1, r0 = quotient Q of division Q = (X x Y) / Z
                          ;           r7, r6, r5, r4 = remainder
                          ;           Carry C is set if Z = 0, i.e. divide by 0 attempted
                          ;
                          ; calls:    UMUL16, UDIV32, Cr0r1, Cr2r3, Cr4r5, Mr0r3
                          ;
                          ; alters:   acc, flags, Bits 21H & 22H
                          ;====================================================================
                          
                          MULDIV:        anl     PSW, #0E7H      ; Register Bank 0
                                         mov     a, r4           ; get divisor high byte
                                         orl     a, r5           ; OR with low byte
                                         jnz     muld_OK         ; divisor OK if not 0
                                         setb    C               ; else, overflow
                                         ret
                          
                          muld_OK:       acall   Cr0r1           ; 2's comp -> Mag/Sign
                                         acall   Cr2r3           ; 2's comp -> Mag/Sign
                                         acall   UMUL16
                                         jb      21H, divn1      ; test X sign
                          divn:          acall   Cr4r5           ; 2's comp -> Mag/Sign
                                         acall   UDIV32
                                         acall   Mr0r3           ; Mag/Sign -> 2's Comp
                                         clr     C               ; divisor is not 0
                                         ret
                          
                          divn1:         jbc     22H, divn       ; test Y sign
                                         setb    22H
                                         sjmp    divn
                          
                          
                          ;====================================================================
                          ; subroutine MACD16
                          ; 16-Bit x 16-Bit to 32-Bit Product signed Multiply-Accumulate
                          ; with table data and data move.
                          ; y(n) = x(n)*h0 + x(n-1)*h1 + x(n-2)*h2 + ......
                          ; x(n-1) = x(n)....
                          ; Note: Assumes shared program/data space. i.e. PSEN and RD are OR-ed
                          ; together on the board.
                          ; 2's Complement format
                          ;
                          ; input:    B = No. of 16-bit data items in tables (max 63)
                          ;           DPTR --> New Input data (e.g. from ADC)
                          ;           DPTR+2 --> Base of Data Table (x)
                          ;           DPTR+128 --> Base of Multiplier Table (h)
                          ;
                          ; output:   r7, r6, r5, r4 = 32-bit accumulated result
                          ;
                          ; calls:    MUL16
                          ;
                          ; alters:   acc, flags, Bits 21H & 22H
                          ;====================================================================
                          
                          MACD16:        anl    PSW, #0E7H
                                         mov    r4, #0           ; Clear Accumulator
                                         mov    r5, #0
                                         mov    r6, #0
                                         mov    r7, #0
                          
                                         movx   a, @DPTR
                                         push   acc              ; Save XNEWL
                                         inc    DPTR
                                         movx   a, @DPTR
                                         push   acc              ; Save XNEWH
                                         inc    DPTR
                          
                          Macd1:         movx   a, @DPTR         ; Get x(n)L
                                         mov    r0, a
                                         push   acc              ; Save x(n)L
                                         mov    a, #80H
                                         movc   a, @a+DPTR       ; Get h(n)L
                                         mov    r2, a
                                         inc    DPTR
                                         movx   a, @DPTR         ; Get x(n)H
                                         mov    r1, a
                                         push   acc              ; Save x(n)H
                                         mov    a, #80H
                                         movc   a, @a+DPTR       ; Get hnH
                                         mov    r3, a
                                         lcall  MUL16+3          ; Do Multiply...
                                         mov    A, r4            ; then Accumulate..
                                         add    A, r0
                                         mov    r4, A
                                         mov    A, r5
                                         addc   A, r1
                                         mov    r5, A
                                         mov    A, r6
                                         addc   A, r2
                                         mov    r6, A
                                         mov    A, r7
                                         addc   A, r3
                                         mov    r7, A
                                         pop    01               ; Now move x data
                                         pop    00
                                         pop    03
                                         pop    02
                                         push   00
                                         push   01
                                         mov    a, r3            ; Move up x(n)H
                                         movx   @DPTR, a
                                         mov    a, #0FFH
                                         add    a, dpl
                                         mov    dpl, a
                                         mov    a, #0FFH
                                         addc   a, dph
                                         mov    dph, a
                                         mov    a, r2            ; Move up x(n)L
                                         movx   @DPTR, a
                                         inc    DPTR
                                         inc    DPTR
                                         djnz   b, Macd1         ; Whole table processed?
                                         dec    SP
                                         dec    SP
                                         ret
                          
                          
                          ;==================================================================
                          ; subroutine DELAY
                          ;
                          ; input:    r0, r1, r2 = delay loop constants, r0 = coarse loop
                          ;==================================================================
                          
                          DELAY:         push   dpl
                                         push   dph
                                         mov    dpl, r1
                                         mov    dph, r2
                          Delay1:        mov    r1, dpl
                          Delay2:        mov    r2, dph
                                         djnz   r2, $
                                         djnz   r1, Delay2
                                         djnz   r0, Delay1
                                         pop    dph
                                         pop    dpl
                                         ret
                          
                          
                          end
                          vẫn còn nữa nhưng tạm thời thế đã.

                          Comment


                          • #14
                            Em có một bài tập mà không biết lam như thế nào cả. Mong bác ngohaibac hay bất cứ bác nào biết thì hướng dẫn em làm bài tâp này cái. Nếu có sẵn thì các bác có thể cho em cả phần cứng hay phần mềm gì cũng OK. Đề bài như thế này:
                            " thiết kế mạch phát xung vuông tần số lập trìng được, có nut ấn chọn tầm Hz, KHz, 100KHz, nút ấn để tăng tần số, nút ấn để giảm tần số. Hiển thị tần số ra led 7 đoạn". ( dùng timer)

                            Comment


                            • #15
                              Chào các bạn,cho mình hỏi là làm sao dùng chân của các port để điều khiển 1 tải dùng điện xoay chiều có dòng khoản vài Ampe?

                              Comment

                              Về tác giả

                              Collapse

                              ngohaibac Tìm hiểu thêm về ngohaibac

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X