I'm working on writing a monitor program for the 8086 using a mix of C and Assembly. While exploring available tools, I came across Slador's toolchain, which I found incredibly useful Hello World!.
To test different execution flows, I simulated the 8086 using Proteus. However, I observed an unexpected behavior when calling functions from main():
Issue: Function Return to the Start of main() The program’s entry point is
RESET: → jmp init → call main().
Inside main(), whenever a function is called, instead of returning to the instruction after the call, execution jumps back to the start of main().
- rest.asm (Entry Point - Calls init)
CPU 8086
BITS 16
%include "system_def.inc"
SECTION .reset
GLOBAL reset
EXTERN init
reset:
jmp SYSTEM_BOOT_SEG:init
- init.m (Initializes Stack & Calls main)
CPU 8086
BITS 16
%include "system_def.inc"
SECTION .text
GLOBAL init
EXTERN __dataoffset
EXTERN __ldata
EXTERN __sbss
EXTERN __lbss
EXTERN main
init:
mov ax, SYSTEM_STACK_SEG
mov ss, ax
xor sp, sp
mov es, ax
mov ax, cs
mov ds, ax
mov si, __dataoffset
xor di, di
mov cx, __ldata
rep movsw
xor ax, ax
mov di, __sbss
mov cx, __lbss
rep stosw
mov ax, ss
mov ds, ax
mov es, ax
call main
jmp $
main.c (Example Code)
#include <stdint.h> #include <stdbool.h> #include <string.h> #include "utils.h" #include "text_lcd.h" void lcd_init() { delay(2000); // Code gets stuck here ... } void main() { lcd_init(); char buffer[16] = "Hello World!"; text_lcd_send_text_at(4, 1, buffer); }
delay Function (Assembly)
delay: push bp mov bp, sp mov cx, [bp + 4] .1: dec cx jnz .1 mov sp, bp pop bp ret
Experiment & Findings: When I modified the flow by placing a jmp main before init, the issue was resolved—functions returned correctly to their respective calling points.
This makes me suspect the issue might be related to stack initialization or how the execution environment is set up.
Questions: Could this be a limitation or quirk of the Proteus 8086 simulation, meaning real hardware would behave correctly?
I noticed in Slador’s video that the code runs correctly on an actual 8088 system—does this confirm that the behavior I'm seeing is just a simulation artifact?
I appreciate any insights from those experienced with real 8086 hardware or debugging in Proteus.