L4. Hybrid programming

Principles of hybrid programming

Caller modules (incl. main program) define the requirements for called modules
callee must not spoil the caller's environments
calee must comply with ABI defined in a given environment, including the calling convention
Usually code written in a higher-level language calls code written in a lower-level language

ABI - Application Binary Interface

Specification of a program behavior and rules

Calling convention

Defines the method for passing the control between routines, passing the argument, receiving function values and rules for using processor resources (registers, stack) by called routines

May be defined by:

Registers in calling convention

Stack pointer
points to top of the stack
Frame pointer
contains base address of addressing objects within the routine's stack frame
not used in some environments
Argument registers
used to pass the arguments to the callee
arguments that cannot be places in registers due to their number, size or type, must be passed using memory stack
Value registers
used to return scalar function values
structures and types that cannot fit in registers are returned on the stack in a place allocated by called
Saved registers
callee must preserve their values for the caller
the routine either doesn't use them or saves them before using and restores before returning to the caller
used for local variable allocation
frame pointer belongs to saved group
Temporary registers
may be used freely by every routine
not preserved by callee
used for intermediate results and addresses, locals in leaf routines
argument and value registers belong to this group

Calling the function

Arguments pushed on the stack
some arguments can be passed in registers but it must be possible to put them to memory stack in case they are later referenced by address
Internal promotion
arguments shorter than int are passed as ints/unsigned ints
reason - (usually) stack references are word-sized

Subroutine prologue

  1. Align the stack (if required)
  2. Save caller's frame pointer (if necessary)
  3. Allocate stack space for arguments passed in registers
  4. Store argument registers if necessary
  5. Set new frame pointer value
  6. Allocate stack space for local data
  7. Save 'saved' registers if used within the routine
    The exact order of actions depends on a calling convention

Subroutine epilogue

  1. restore saved registers
  2. deallocate local variables
  3. restore caller's frame pointer
  4. discard other data from stack if needed
  5. return

RISC-V calling convention

Assigns mnemonic names to processor registers
Up to 8 arguments passed in registers
Up to 9 local data objecta in registers - saved group
No support for stack in instruction set
University/WUT/ECOAR/pictures/Pasted image 20250414232218.png


Unix System V x86 calling convention

Defined by Unix designers, used in all Unix-like systems
In basic aspects - compatible with C calling convention used unsed 32-bit Windows
University/WUT/ECOAR/pictures/Pasted image 20250414232358.png
Current calling convention requires the ESP to be aligned to a boundary of at least 16 immediately before the procedure call
the address of the first argument of a procedure it n×16
This is achieved by adjusting the ESP before pushing the arguments
Arguments may be placed on the stack by using PUSH or (after adjusting ESP) MOV [EBP + disp]
After the frame pointer is set, the first argument is at [EBP + 8]

; prologue
	push ebp
	mov ebp, esp
	; ESP == n*16 + 8
	sub esp, (LOCAL_DATA_SIZE + 3) & ~3 ; allocate locals if needed

	; save 'saved' registers if used
	push ebx
	push esi
	push edi
;---------------------
; code
;---------------------
; epilogue
	; restore saved registers if they were saved in the prologue
	pop edi
	pop esi
	pop ebx
	
	mov esp, ebp
	pop ebp
	ret

The order of actions MUST NOT be altered!

x86-64 Unix/Linux ABI calling convention

64-bit addresses
stack data - min. 64 bits, size-aligned
up to 6 integer and 4 floating-point arguments passed in registers
stack must be aligned to at least 16-byte boundary when executing CALL
University/WUT/ECOAR/pictures/Pasted image 20250414234255.png

Stack frame

Stack must be aligned to 16-/32-byte bounrady when transferring the control between routines
all items on the stack are size-aligned regardless of their size
location of first argument is fixed - right after return trace
After CALL and PUSH RBP (2×8 bytes)stack is aligned to 16 bytes

Windows x64 (x86-64) calling convention

Defined by Microsoft, used in 64-bit Windows family systems running on x86-64
Significantly different from Linux/Unix convention despite being for the same architecture
Similar to RISC conventions
uses registers for arguments and local variables
Enforces stack alignment to 16-byte boundary

Registers

16 g.p. registers, including RSP (stack pointer) and RBP (frame pointer)
16 floating-point/vector registers in SSE unit
University/WUT/ECOAR/pictures/Pasted image 20250414234830.png

Stack frame

First four scalar arguments in registers
caller reserves space on stack for saving the arguments in called routine
Before CALL stack is aligned to 16-byte boundary
Locals are allocatedafter saving caller's registers
Frame pointer points to the first local
University/WUT/ECOAR/pictures/Pasted image 20250414235006.png