mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 17:49:33 +02:00
791 lines
17 KiB
NASM
791 lines
17 KiB
NASM
; common startup code for all the memory models
|
|
|
|
; uncomment this, if you want to use i8086 section based smartlinking:
|
|
;%define __I8086_SMARTLINK_SECTIONS__
|
|
|
|
%ifdef __TINY__
|
|
%define __NEAR_CODE__
|
|
%define __NEAR_DATA__
|
|
%elifdef __SMALL__
|
|
%define __NEAR_CODE__
|
|
%define __NEAR_DATA__
|
|
%elifdef __MEDIUM__
|
|
%define __FAR_CODE__
|
|
%define __NEAR_DATA__
|
|
%elifdef __COMPACT__
|
|
%define __NEAR_CODE__
|
|
%define __FAR_DATA__
|
|
%elifdef __LARGE__
|
|
%define __FAR_CODE__
|
|
%define __FAR_DATA__
|
|
%elifdef __HUGE__
|
|
%define __FAR_CODE__
|
|
%define __FAR_DATA__
|
|
%else
|
|
%fatal "Memory model not defined."
|
|
%endif
|
|
|
|
%ifdef __FAR_CODE__
|
|
extra_param_offset equ 2
|
|
%else
|
|
extra_param_offset equ 0
|
|
%endif
|
|
|
|
%ifdef __FAR_DATA__
|
|
extra_data_offset equ 2
|
|
%else
|
|
extra_data_offset equ 0
|
|
%endif
|
|
|
|
cpu 8086
|
|
|
|
segment _TEXT use16 class=CODE
|
|
|
|
extern PASCALMAIN
|
|
extern __fpc_PrefixSeg
|
|
extern dos_version
|
|
extern __Test8086
|
|
|
|
extern _edata ; defined by WLINK, indicates start of BSS
|
|
extern _end ; defined by WLINK, indicates end of BSS
|
|
|
|
extern __stklen
|
|
extern __stktop
|
|
extern __stkbottom
|
|
|
|
extern __nearheap_start
|
|
extern __nearheap_end
|
|
|
|
extern ___heap
|
|
|
|
%ifdef __NEAR_DATA__
|
|
extern __fpc_stackplusmaxheap_in_para
|
|
%endif
|
|
|
|
%ifndef __TINY__
|
|
%ifdef __FAR_DATA__
|
|
extern ___stack
|
|
%endif
|
|
%ifdef __NEAR_DATA__
|
|
extern ___stacktop
|
|
%endif
|
|
%endif
|
|
|
|
extern __SaveInt00
|
|
extern __SaveInt10
|
|
extern __SaveInt75
|
|
|
|
extern __fpu_status
|
|
|
|
extern FPC_HANDLE_I8086_ERROR
|
|
|
|
%ifdef __TINY__
|
|
resb 0100h
|
|
%endif
|
|
..start:
|
|
%ifndef __HUGE__
|
|
%ifdef __TINY__
|
|
mov bx, cs
|
|
%else
|
|
mov bx, DGROUP
|
|
%ifdef __NEAR_DATA__
|
|
; init the stack
|
|
mov ss, bx
|
|
mov sp, ___stacktop wrt DGROUP
|
|
%endif
|
|
%endif
|
|
|
|
; zero fill the BSS section
|
|
mov es, bx
|
|
mov di, _edata wrt DGROUP
|
|
mov cx, _end wrt DGROUP
|
|
sub cx, di
|
|
xor al, al
|
|
cld
|
|
rep stosb
|
|
%endif ; not __HUGE__
|
|
|
|
; save the Program Segment Prefix
|
|
push ds
|
|
|
|
; init DS
|
|
%ifdef __HUGE__
|
|
mov bx, SYSTEM_DATA
|
|
mov ds, bx
|
|
%else
|
|
mov ds, bx
|
|
%endif
|
|
|
|
; pop the PSP from stack and store it in the pascal variable PrefixSeg
|
|
pop ax
|
|
mov word [__fpc_PrefixSeg], ax
|
|
|
|
; get DOS version and save it in the pascal variable dos_version
|
|
mov ax, 3000h
|
|
int 21h
|
|
xchg al, ah
|
|
mov word [dos_version], ax
|
|
|
|
; detect CPU
|
|
xor bx, bx ; 0=8086/8088/80186/80188/NEC V20/NEC V30
|
|
; on pre-286 processors, bits 12..15 of the FLAGS registers are always set
|
|
pushf
|
|
pop ax
|
|
and ah, 0fh
|
|
push ax
|
|
popf
|
|
pushf
|
|
pop ax
|
|
and ah, 0f0h
|
|
cmp ah, 0f0h
|
|
je cpu_detect_done
|
|
; at this point we have a 286 or higher
|
|
inc bx
|
|
; on a true 286 in real mode, bits 12..15 are always clear
|
|
pushf
|
|
pop ax
|
|
or ah, 0f0h
|
|
push ax
|
|
popf
|
|
pushf
|
|
pop ax
|
|
and ah, 0f0h
|
|
jz cpu_detect_done
|
|
; we have a 386+
|
|
inc bx
|
|
|
|
cpu_detect_done:
|
|
mov [__Test8086], bl
|
|
|
|
%ifdef __NEAR_DATA__
|
|
; ****************************************************************************
|
|
; ** near data memory layout setup **
|
|
; ****************************************************************************
|
|
|
|
; allocate max heap
|
|
; first we determine in paragraphs ax:=min(64kb, data+bss+stack+maxheap)
|
|
mov ax, _end wrt DGROUP
|
|
add ax, 15
|
|
mov cl, 4
|
|
shr ax, cl
|
|
add ax, word [__fpc_stackplusmaxheap_in_para]
|
|
cmp ax, 1000h ; 1000h = 64k in paragraphs
|
|
jbe data_with_maxheap_less_than_64k
|
|
mov ax, 1000h
|
|
data_with_maxheap_less_than_64k:
|
|
|
|
; try to resize our main DOS memory block until the end of the data segment (or even smaller, if maxheap is small)
|
|
mov cx, word [__fpc_PrefixSeg]
|
|
%ifdef __TINY__
|
|
mov dx, cs
|
|
%else
|
|
mov dx, DGROUP
|
|
%endif
|
|
sub dx, cx ; dx = (ds - psp) in paragraphs
|
|
push dx ; save (ds - psp)
|
|
add dx, 1000h ; 64kb in paragraphs
|
|
|
|
; get our MCB size in paragraphs
|
|
dec cx
|
|
mov es, cx
|
|
mov bx, word [es:3]
|
|
|
|
; is it smaller than the maximum data segment size?
|
|
cmp bx, dx
|
|
jbe skip_mem_realloc
|
|
|
|
mov bx, dx
|
|
inc cx
|
|
mov es, cx
|
|
mov ah, 4Ah
|
|
int 21h
|
|
jc mem_realloc_err
|
|
|
|
skip_mem_realloc:
|
|
|
|
; bx = the new size in paragraphs
|
|
pop cx ; cx = (ds - psp)
|
|
sub bx, cx
|
|
mov cl, 4
|
|
shl bx, cl
|
|
sub bx, 2
|
|
mov sp, bx
|
|
|
|
mov word [__stktop], sp
|
|
add bx, 2
|
|
sub bx, word [__stklen]
|
|
and bl, 0FEh
|
|
mov word [__stkbottom], bx
|
|
|
|
mov ax, _end wrt DGROUP
|
|
cmp bx, ax
|
|
jb not_enough_mem
|
|
|
|
; heap is between [ds:_end wrt DGROUP] and [ds:__stkbottom - 1]
|
|
add ax, 3
|
|
and al, 0FCh
|
|
mov word [__nearheap_start], ax
|
|
and bl, 0FCh
|
|
mov word [__nearheap_end], bx
|
|
|
|
; ****************************************************************************
|
|
; ** near data setup done **
|
|
; ****************************************************************************
|
|
%endif
|
|
|
|
|
|
%ifdef __FAR_DATA__
|
|
mov word [__stktop], sp
|
|
mov word [__stkbottom], 0
|
|
mov ax, ss
|
|
mov word [__stkbottom + 2], ax
|
|
mov word [__stktop + 2], ax
|
|
|
|
mov dx, sp
|
|
add dx, 15
|
|
mov cl, 4
|
|
shr dx, cl
|
|
add ax, dx
|
|
mov word [__nearheap_start], 0
|
|
mov word [__nearheap_start + 2], ax
|
|
|
|
; get our MCB size in paragraphs
|
|
mov cx, word [__fpc_PrefixSeg]
|
|
dec cx
|
|
mov es, cx
|
|
mov bx, word [es:3]
|
|
add bx, cx
|
|
inc bx
|
|
; __nearheap_end := end_of_dos_memory_block
|
|
mov word [__nearheap_end], 0
|
|
mov word [__nearheap_end + 2], bx
|
|
%endif
|
|
|
|
%ifdef __FAR_CODE__
|
|
jmp far PASCALMAIN
|
|
%else
|
|
jmp PASCALMAIN
|
|
%endif
|
|
|
|
%ifdef __NEAR_DATA__
|
|
not_enough_mem:
|
|
mov dx, not_enough_mem_msg
|
|
jmp error_msg
|
|
|
|
mem_realloc_err:
|
|
; at this point there's still (ds-psp) pushed on the stack, but we won't
|
|
; bother popping it, because we exit to DOS with an error message here
|
|
mov dx, mem_realloc_err_msg
|
|
error_msg:
|
|
mov ah, 9
|
|
int 21h
|
|
mov ax, 4CFFh
|
|
int 21h
|
|
%endif
|
|
|
|
global FPC_INT00_HANDLER
|
|
FPC_INT00_HANDLER:
|
|
pushf
|
|
sub sp, 4 ; reserve space on the stack for the iret
|
|
|
|
push cx
|
|
push ds
|
|
push bp
|
|
|
|
; init ds
|
|
%ifdef __TINY__
|
|
mov bp, cs
|
|
%elifdef __HUGE__
|
|
mov bp, SYSTEM_DATA
|
|
%else
|
|
mov bp, DGROUP
|
|
%endif
|
|
mov ds, bp
|
|
|
|
%ifdef __NEAR_DATA__
|
|
; in memory models, where SS=DS, also
|
|
; check whether we're running on the same stack
|
|
mov cx, ss
|
|
cmp bp, cx
|
|
jne .call_previous_handler00
|
|
%endif
|
|
|
|
%ifndef __FAR_CODE__
|
|
; check whether we're coming from the same code segment
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
mov bp, cs
|
|
cmp bp, cx
|
|
jne .call_previous_handler00
|
|
%endif
|
|
|
|
; Call Fpc_Handle_I8086_Error, with err=0
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
|
%ifdef __FAR_CODE__
|
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
%endif
|
|
pop bp
|
|
add sp, 2*2 + 6 + 6
|
|
xor ax, ax
|
|
push ax
|
|
mov ax, 0
|
|
push ax
|
|
%ifdef __FAR_CODE__
|
|
push dx
|
|
%endif
|
|
push cx
|
|
cld
|
|
sti
|
|
%ifdef __FAR_CODE__
|
|
jmp far FPC_HANDLE_I8086_ERROR
|
|
%else
|
|
jmp FPC_HANDLE_I8086_ERROR
|
|
%endif
|
|
|
|
.call_previous_handler00:
|
|
mov bp, sp
|
|
mov cx, [__SaveInt00]
|
|
mov [bp + 3*2], cx
|
|
mov cx, [__SaveInt00+2]
|
|
mov [bp + 3*2 + 2], cx
|
|
pop bp
|
|
pop ds
|
|
pop cx
|
|
iret ; jumps to the previous handler with all registers and stack intact
|
|
|
|
global FPC_INT10_HANDLER
|
|
FPC_INT10_HANDLER:
|
|
pushf
|
|
sub sp, 4 ; reserve space on the stack for the iret
|
|
|
|
push cx
|
|
push ds
|
|
push bp
|
|
|
|
; init ds
|
|
%ifdef __TINY__
|
|
mov bp, cs
|
|
%elifdef __HUGE__
|
|
mov bp, SYSTEM_DATA
|
|
%else
|
|
mov bp, DGROUP
|
|
%endif
|
|
mov ds, bp
|
|
; Check that an unmasked exception is indeed set
|
|
fnstsw word [__fpu_status]
|
|
test byte [__fpu_status], 80h ; really just this bit is enough, see i8087 datasheet
|
|
je .call_previous_handler10
|
|
|
|
%ifdef __NEAR_DATA__
|
|
; in memory models, where SS=DS, also
|
|
; check whether we're running on the same stack
|
|
mov cx, ss
|
|
cmp bp, cx
|
|
jne .call_previous_handler10
|
|
%endif
|
|
|
|
%ifndef __FAR_CODE__
|
|
; check whether we're coming from the same code segment
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
mov bp, cs
|
|
cmp bp, cx
|
|
jne .call_previous_handler10
|
|
%endif
|
|
|
|
; Call Fpc_Handle_I8086_Error, with err=$10
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
|
%ifdef __FAR_CODE__
|
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
%endif
|
|
pop bp
|
|
add sp, 2*2 + 6 + 6
|
|
xor ax, ax
|
|
push ax
|
|
mov ax, 10h
|
|
push ax
|
|
%ifdef __FAR_CODE__
|
|
push dx
|
|
%endif
|
|
push cx
|
|
cld
|
|
sti
|
|
%ifdef __FAR_CODE__
|
|
jmp far FPC_HANDLE_I8086_ERROR
|
|
%else
|
|
jmp FPC_HANDLE_I8086_ERROR
|
|
%endif
|
|
|
|
.call_previous_handler10:
|
|
mov bp, sp
|
|
mov cx, [__SaveInt10]
|
|
mov [bp + 3*2], cx
|
|
mov cx, [__SaveInt10+2]
|
|
mov [bp + 3*2 + 2], cx
|
|
pop bp
|
|
pop ds
|
|
pop cx
|
|
iret ; jumps to the previous handler with all registers and stack intact
|
|
|
|
global FPC_INT75_HANDLER
|
|
FPC_INT75_HANDLER:
|
|
pushf
|
|
sub sp, 4 ; reserve space on the stack for the iret
|
|
|
|
push cx
|
|
push ds
|
|
push bp
|
|
|
|
; init ds
|
|
%ifdef __TINY__
|
|
mov bp, cs
|
|
%elifdef __HUGE__
|
|
mov bp, SYSTEM_DATA
|
|
%else
|
|
mov bp, DGROUP
|
|
%endif
|
|
mov ds, bp
|
|
|
|
%ifdef __NEAR_DATA__
|
|
; in memory models, where SS=DS, also
|
|
; check whether we're running on the same stack
|
|
mov cx, ss
|
|
cmp bp, cx
|
|
jne .call_previous_handler75
|
|
%endif
|
|
|
|
%ifndef __FAR_CODE__
|
|
; check whether we're coming from the same code segment
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
mov bp, cs
|
|
cmp bp, cx
|
|
jne .call_previous_handler75
|
|
%endif
|
|
|
|
; Call Fpc_Handle_I8086_Error, with err=$75
|
|
mov bp, sp
|
|
mov cx, [bp + 3*2 + 6] ; get caller offset
|
|
%ifdef __FAR_CODE__
|
|
mov dx, [bp + 3*2 + 6 + 2] ; get caller segment
|
|
%endif
|
|
pop bp
|
|
add sp, 2*2 + 6 + 6
|
|
xor ax, ax
|
|
push ax
|
|
mov ax, 75h
|
|
push ax
|
|
%ifdef __FAR_CODE__
|
|
push dx
|
|
%endif
|
|
push cx
|
|
cld
|
|
|
|
; Reset IRQ/#IGNNE latch; signal EOI; enable interrupts
|
|
mov al,20h
|
|
out 0F0h,al ; al=any
|
|
out 0A0h,al
|
|
out 020h,al
|
|
sti
|
|
|
|
%ifdef __FAR_CODE__
|
|
jmp far FPC_HANDLE_I8086_ERROR
|
|
%else
|
|
jmp FPC_HANDLE_I8086_ERROR
|
|
%endif
|
|
|
|
.call_previous_handler75:
|
|
mov bp, sp
|
|
mov cx, [__SaveInt75]
|
|
mov [bp + 3*2], cx
|
|
mov cx, [__SaveInt75+2]
|
|
mov [bp + 3*2 + 2], cx
|
|
pop bp
|
|
pop ds
|
|
pop cx
|
|
retf ; jumps to the previous handler with all registers and stack intact
|
|
|
|
|
|
|
|
global FPC_INSTALL_INTERRUPT_HANDLERS
|
|
FPC_INSTALL_INTERRUPT_HANDLERS:
|
|
|
|
%ifdef __HUGE__
|
|
push ds
|
|
mov ax, SYSTEM_DATA
|
|
mov ds, ax
|
|
%endif
|
|
|
|
; save old int 00 handler
|
|
mov ax, 3500h
|
|
int 21h
|
|
mov [__SaveInt00], bx
|
|
mov bx, es
|
|
mov [__SaveInt00+2], bx
|
|
|
|
; install the new int 00 handler
|
|
%ifndef __TINY__
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
%endif
|
|
mov dx, FPC_INT00_HANDLER
|
|
mov ax, 2500h
|
|
int 21h
|
|
%ifndef __TINY__
|
|
pop ds
|
|
%endif
|
|
|
|
; save old int $10 handler
|
|
mov ax, 3510h
|
|
int 21h
|
|
mov [__SaveInt10], bx
|
|
mov bx, es
|
|
mov [__SaveInt10+2], bx
|
|
|
|
; install the new int $10 handler
|
|
%ifndef __TINY__
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
%endif
|
|
mov dx, FPC_INT10_HANDLER
|
|
mov ax, 2510h
|
|
int 21h
|
|
%ifndef __TINY__
|
|
pop ds
|
|
%endif
|
|
|
|
; save old int $75 handler
|
|
mov ax, 3575h
|
|
int 21h
|
|
mov [__SaveInt75], bx
|
|
mov bx, es
|
|
mov [__SaveInt75+2], bx
|
|
|
|
; install the new int $75 handler
|
|
%ifndef __TINY__
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
%endif
|
|
mov dx, FPC_INT75_HANDLER
|
|
mov ax, 2575h
|
|
int 21h
|
|
%ifndef __TINY__
|
|
pop ds
|
|
%endif
|
|
|
|
|
|
%ifdef __HUGE__
|
|
pop ds
|
|
%endif
|
|
%ifdef __FAR_CODE__
|
|
retf
|
|
%else
|
|
ret
|
|
%endif
|
|
|
|
|
|
global FPC_RESTORE_INTERRUPT_HANDLERS
|
|
FPC_RESTORE_INTERRUPT_HANDLERS:
|
|
|
|
%ifdef __HUGE__
|
|
push ds
|
|
mov ax, SYSTEM_DATA
|
|
mov ds, ax
|
|
%endif
|
|
push ds
|
|
mov ax, 2500h
|
|
lds dx, [__SaveInt00]
|
|
int 21h
|
|
pop ds
|
|
|
|
push ds
|
|
mov ax, 2510h
|
|
lds dx, [__SaveInt10]
|
|
int 21h
|
|
pop ds
|
|
|
|
push ds
|
|
mov ax, 2575h
|
|
lds dx, [__SaveInt75]
|
|
int 21h
|
|
pop ds
|
|
|
|
%ifdef __HUGE__
|
|
pop ds
|
|
%endif
|
|
%ifdef __FAR_CODE__
|
|
retf
|
|
%else
|
|
ret
|
|
%endif
|
|
|
|
|
|
global FPC_MSDOS_CARRY
|
|
FPC_MSDOS_CARRY:
|
|
stc
|
|
global FPC_MSDOS
|
|
FPC_MSDOS:
|
|
mov al, 21h ; not ax, because only the low byte is used
|
|
pop dx
|
|
%ifdef __FAR_CODE__
|
|
pop bx
|
|
%endif
|
|
pop cx
|
|
%ifdef __FAR_DATA__
|
|
pop si
|
|
%endif
|
|
push ax
|
|
%ifdef __FAR_DATA__
|
|
push si
|
|
%endif
|
|
push cx
|
|
%ifdef __FAR_CODE__
|
|
push bx
|
|
%endif
|
|
push dx
|
|
global FPC_INTR
|
|
FPC_INTR:
|
|
push bp
|
|
mov bp, sp
|
|
mov al, byte [bp + 6 + extra_param_offset + extra_data_offset]
|
|
mov byte [cs:int_number], al
|
|
mov si, [bp + 4 + extra_param_offset]
|
|
push ds
|
|
%ifdef __FAR_DATA__
|
|
mov ax, [bp + 6 + extra_param_offset]
|
|
mov ds, ax
|
|
%endif
|
|
mov ax, word [si + 16]
|
|
mov es, ax
|
|
mov ax, word [si + 14] ; ds
|
|
push ax
|
|
mov ax, word [si]
|
|
mov bx, word [si + 2]
|
|
mov cx, word [si + 4]
|
|
mov dx, word [si + 6]
|
|
mov bp, word [si + 8]
|
|
mov di, word [si + 12]
|
|
mov si, word [si + 10]
|
|
|
|
pop ds
|
|
db 0CDh ; opcode of INT xx
|
|
int_number:
|
|
db 255
|
|
|
|
pushf
|
|
push ds
|
|
push si
|
|
push bp
|
|
mov bp, sp
|
|
%ifdef __FAR_DATA__
|
|
mov si, [bp + 16 + extra_param_offset]
|
|
%else
|
|
mov si, word [bp + 8]
|
|
%endif
|
|
mov ds, si
|
|
mov si, word [bp + 14 + extra_param_offset]
|
|
mov word [si], ax
|
|
mov word [si + 2], bx
|
|
mov word [si + 4], cx
|
|
mov word [si + 6], dx
|
|
mov word [si + 12], di
|
|
mov ax, es
|
|
mov word [si + 16], ax
|
|
pop ax
|
|
mov word [si + 8], ax
|
|
pop ax
|
|
mov word [si + 10], ax
|
|
pop ax
|
|
mov word [si + 14], ax
|
|
pop ax
|
|
mov word [si + 18], ax
|
|
|
|
pop ds
|
|
pop bp
|
|
%ifdef __FAR_CODE__
|
|
retf 4 + extra_data_offset
|
|
%else
|
|
ret 4 + extra_data_offset
|
|
%endif
|
|
|
|
%ifndef __TINY__
|
|
global FPC_CHECK_NULLAREA
|
|
FPC_CHECK_NULLAREA:
|
|
%ifdef __HUGE__
|
|
mov ax, DGROUP
|
|
mov es, ax
|
|
%else
|
|
push ds
|
|
pop es
|
|
%endif
|
|
xor di, di
|
|
mov cx, 32
|
|
mov al, 1
|
|
cld
|
|
repe scasb
|
|
je .skip
|
|
dec ax ; 1 byte shorter than dec al
|
|
.skip:
|
|
%ifdef __FAR_CODE__
|
|
retf
|
|
%else
|
|
ret
|
|
%endif
|
|
%endif
|
|
|
|
%ifdef __HUGE__
|
|
; reference the system unit's data segment
|
|
segment SYSTEM_DATA use16 class=FAR_DATA align=2
|
|
%endif
|
|
|
|
segment data class=DATA align=2
|
|
%ifdef __NEAR_DATA__
|
|
mem_realloc_err_msg:
|
|
db 'Memory allocation error', 13, 10, '$'
|
|
not_enough_mem_msg:
|
|
db 'Not enough memory', 13, 10, '$'
|
|
%endif
|
|
; add reference to the beginning of the minimal heap, so the object
|
|
; module, containing the heap segment doesn't get smartlinked away
|
|
dw ___heap
|
|
|
|
segment bss class=BSS align=2
|
|
|
|
%ifndef __TINY__
|
|
segment _NULL align=16 class=BEGDATA
|
|
global __nullarea
|
|
__nullarea:
|
|
dd 01010101h, 01010101h, 01010101h, 01010101h
|
|
dd 01010101h, 01010101h, 01010101h, 01010101h
|
|
|
|
segment _AFTERNULL align=2 class=BEGDATA
|
|
dw 0
|
|
|
|
%ifdef __NEAR_DATA__
|
|
segment stack stack class=STACK align=16
|
|
%else
|
|
segment data
|
|
; add reference to the beginning of stack, so the object module,
|
|
; containing the stack segment doesn't get smartlinked away
|
|
dw ___stack
|
|
%endif
|
|
%endif
|
|
|
|
%ifdef __TINY__
|
|
group DGROUP _TEXT data bss
|
|
%else
|
|
%ifdef __NEAR_DATA__
|
|
group DGROUP _NULL _AFTERNULL data bss stack
|
|
%else
|
|
group DGROUP _NULL _AFTERNULL data bss
|
|
%endif
|
|
%ifdef __I8086_SMARTLINK_SECTIONS__
|
|
group CGROUP _TEXT
|
|
%endif
|
|
%endif
|