Inline Assembly & Interrupt Functions

Hello,
1) I want to place assembly code in my C code. The problem with using SRC is that I would have to rename the file MyAsm.SRC to MyAsm.A51 and then (remove C code from project) include A51 code in the project... before finally recompiling the whole project. Is there any way to just add assembly code without using SRC?
What about the '__asm' keyword? Where do I get more info on this?

2) The Cx51 User Manual (Pg124) states that the Interrupt function will save SFR, ACC, B, DPL, DPH etc 'when required' to stack (and later pop it). How do I disable this feature so I can manually do the PUSHing and POPing? If this is not possible then is it possible to instruct Keil to 'save all' registers regardless of need?

Regards,
KC

Parents
  • Hi Ken,

    that SRC thing is just a help for you to build the structure of a function. You just do it once, just typing in the function with its parameters and return value, use the parameters in the function in a simple (dummy) way, then you get assembly code, that declares the segments etc. and shows you where you will find your parameters. This is done once. You "steal" that assembly code mand do all the programming in assembler, never use the SRC pragma again.

    For example, if you want to write an assembly module that handles an LCD display, you first set up a "Prototyping C-source" lcd_prot.c that looks like this:

    #pragma SRC
    
    bit lcd_busy( void ) {
      return 1;
    }
    
    void lcd_out( unsigned char out_byte, unsigned char ram ) {
      if (ram) {
        out_byte++;
      }
    }
    
    void lcd_outchar( unsigned char out_byte ) {
      out_byte++;
    }
    
    void lcd_outinstr( unsigned char out_byte ) {
      out_byte++;
    } 
     
    void lcd_clear( void ) {
      unsigned char byte;
      
      byte++;
    }
    
    void lcd_init( void ) {
      unsigned char byte;
      
      byte++;
    }
    

    This doesn't do anthing reasonable, but when you compile it, you will get a file *.src that looks like this:
    ; c:\c51\proj\Test\lcd.SRC generated from: c:\c51\proj\Test\lcd.c
    
    
    NAME	LCD
    
    ?PR?lcd_busy?LCD     SEGMENT CODE 
    ?PR?_lcd_out?LCD     SEGMENT CODE 
    ?PR?_lcd_outchar?LCD SEGMENT CODE 
    ?PR?_lcd_outinstr?LCD                    SEGMENT CODE 
    ?PR?lcd_clear?LCD    SEGMENT CODE 
    ?XD?lcd_clear?LCD    SEGMENT XDATA OVERLAYABLE 
    ?PR?lcd_init?LCD     SEGMENT CODE 
    ?XD?lcd_init?LCD     SEGMENT XDATA OVERLAYABLE 
    ?PR?_lcd_gotoxy?LCD  SEGMENT CODE 
    ?PR?lcd_clreol?LCD   SEGMENT CODE 
    ?XD?lcd_clreol?LCD   SEGMENT XDATA OVERLAYABLE 
    	PUBLIC	lcd_clreol
    	PUBLIC	_lcd_gotoxy
    	PUBLIC	lcd_init
    	PUBLIC	lcd_clear
    	PUBLIC	_lcd_outinstr
    	PUBLIC	_lcd_outchar
    	PUBLIC	_lcd_out
    	PUBLIC	lcd_busy
    
    	RSEG  ?XD?lcd_clreol?LCD
           byte?545:   DS   1
    ; #pragma SRC
    ; #pragma LARGE
    ; 
    ; bit lcd_busy( void ) {
    
    	RSEG  ?PR?lcd_busy?LCD
    lcd_busy:
    			; SOURCE LINE # 4
    ;   return 1;
    			; SOURCE LINE # 5
    	SETB 	C
    ; }
    			; SOURCE LINE # 6
    ?C0001:
    	RET  	
    ; END OF lcd_busy
    [...]
    

    This lets you recognize the returnvalue of lcd_busy easily... it is contained in the Carry-Bit. Just copy the code and fill the structure with something reasonable written in assembler.

Reply Children
More questions in this forum