0

I have a project in college where the main in asm has to call a function in c, but I don't know how to initialize the stack (rstack and cstack). I mention that the project is on an atmega16. Main asm code:

PUBLIC  main
EXTERN  par, calc
ORG $0     
RJMP    Reset 
RSEG    CODE
Reset:
LDI     R16, HIGH(RAMEND) 
OUT     SPH, R16         
LDI     R16, LOW(RAMEND)  
OUT     SPL, R16          

RJMP    main
RSEG    CODE
main:
LDI     R16, 2       
LDI     R17, 8       
subi    R16, 255     

CALL    calc         
MOV     R22, R16     

CALL    par           
NOP                   

END  

I tried on GPT but it is not working.

2
  • 1
    What issue do you have? How do you compile your C code and how do you link? Commented Jan 3 at 18:00
  • Welcome to StackOverflow! Please take the tour to learn how this site works, and read "How to Ask" and other pages of the help center. Then come back and edit your question to add some background. For example, even if we can guess what you mean by rstack and cstack, please clarify. And LLMs are no good teachers for uninitiated developers... Commented Jan 3 at 18:44

1 Answer 1

0

It's not possible to answer that question without a specific toolchain / binary format in mind. Therefore I am answering the question in the context of the GNU tools for AVR, which is in widespread use and freely available. (For Clang/LLVM it's basically the same since they use the same ABI like avr-gcc, what's different though will be the command line options that have to be used).

Combining Assembly with C/C++

The route to get from source code to binary (skipping features like LTO) is:

  1. Compile a C/C++ source to assemlby code.
  2. Assemble that assembly code to object code (ELF).
  3. Link all the object files and suuport libraries to final executable (ELF).

In the case of assembly code, you can start at 2. So suppose we have an assembly code in main.asm and C code in calc.c. So the commands you will be using are, respectively:

  1. > avr-gcc -mmcu=atmega16 -c calc.c -Os
  2. > avr-gcc -mmcu=atmega16 -c -x assembler-with-cpp main.asm
  3. > avr-gcc -mmcu=atmega16 calc.o main.o -o main.elf

Some notes:

  • avr-gcc is a driver program that compiler / assembles the provided files and determines what to do with them according to their file extension. It recognizes extensions .sx and .S as "assembly with C preprocessor". .asm is not a recognized file extension, hence you have to tell avr-gcc that it is "assembly with C preprocessor".

  • You can do in in one command line, like:
    > avr-gcc -mmcu=atmega16 -x assembler-with-cpp file1.asm ... -x none module1.c ... -Os -o main.elf

calc.c

This is straight forward C code:

#include <stdint.h>

uint8_t calc (uint16_t *pvar)
{
    uint16_t var16 = *pvar;
    
    return var16 <= 255 ? var16 : 255;
}

main.asm

The code below shows some basic functionalities (defining global functions, defining variables, defining ISR). You may also find these links helpful:

;; Define __SFR_OFFSET to 0x0 so we can use SFR addresses like PORTB
;; in  SBI PORTB, ... etc.
#define __SFR_OFFSET 0x0

;; Define stuff like PORTB.
#include <avr/io.h>

;; Convenience macros for start and end of a global function.
.macro DEFUN name
    .global \name
    .type \name, @function
    \name:
.endm

.macro ENDF name
    .size \name, . - \name
.endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.text

;; No need for explicit vector table.  The CRT brings it all.

;; Implement some ISR
DEFUN INT0_vect
    ;; Code for INT0 ISR
    sbi PORTB, 0
    reti
ENDF INT0_vect


;; No preparation / explicit startup code need.  The CRT will setup
;; the device according to the ABI and then call main.

DEFUN main
    ldi R24, lo8(pvar)
    ldi R25, hi8(pvar)
    call calc
    ;; Do something with R24
    rjmp main
ENDF main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.bss

.type var16, @object
var16:
    .zero 2
.size var16, 2

;; Pull in the part of the CRT that clears .bss.
.global __do_clear_bss

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data

.type pvar, @object
pvar:
    .word var16
.size pvar, 2

;; Pull in the part of the CRT that initialized .data.
.global __do_copy_data

The result

> avr-objdump -d main.elf

Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 2a 00     jmp 0x54    ; 0x54 <__init>
   4:   0c 94 49 00     jmp 0x92    ; 0x92 <__vector_1>
   8:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
...
00000054 <__init>:
  54:   11 24           clr r1
  56:   1f be           out 0x3f, r1    ; 63
  58:   cf e5           ldi r28, 0x5F   ; 95
  5a:   d4 e0           ldi r29, 0x04   ; 4
  5c:   de bf           out 0x3e, r29   ; 62
  5e:   cd bf           out 0x3d, r28   ; 61

00000060 <__do_copy_data>:
  ...

00000076 <__do_clear_bss>:
  ...

00000086 <.init9>:
  86:   0e 94 4b 00     call 0x96   ; 0x96 <main>
  8a:   0c 94 56 00     jmp  0xac   ; 0xac <_exit>

0000008e <__bad_interrupt>:
  8e:   0c 94 00 00     jmp 0   ; 0x0 <__vectors>

00000092 <__vector_1>:
  92:   c0 9a           sbi 0x18, 0
  94:   18 95           reti

00000096 <main>:
  96:   80 e6           ldi r24, 0x60   ; 96
  98:   90 e0           ldi r25, 0x00   ; 0
  9a:   0e 94 50 00     call    0xa0    ; 0xa0 <calc>
  9e:   fb cf           rjmp    .-10    ; 0x96 <main>

000000a0 <calc>:
  a0:   fc 01           movw  r30, r24
  a2:   80 81           ld    r24, Z
  a4:   91 81           ldd   r25, Z+1
  a6:   91 11           cpse  r25, r1
  a8:   8f ef           ldi   r24, 0xFF
  aa:   08 95           ret

000000ac <_exit>:
  ac:   f8 94           cli

000000ae <__stop_program>:
  ae:   ff cf           rjmp    .-2         ; 0xae <__stop_program>

rstack or cstack?

avr-gcc only uses ONE stack as initialized by the CRT. The startup code sets SP to point to the end of the internal SRAM (more precidely, it initialized SP with the value of symbol __stack, which defaults to RAMEND).

This stack is used for function return addresses, local variables that didn't get a hard register, function arguments that are passed on the stack, and hard registers that have to be spilled.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.