NASM Forum > Programming with NASM

creating a flat binary bigger than 64kB

(1/2) > >>

Folkert van Heusden:
Hello,

For fun I'm developing an IBM PC emulator (before XT even). At the point it currently is I'm working on test-code to verify that the processor emulation is correct.
Unfortunately I'm stuck on far/inter-segment jumps.
According to http://computer-programming-forum.com/46-asm/bf904883c2cb61c7.htm it is/was possible to create binaries > 64kB yet in practice this fails.
e.g.:

   org 0x800

   xor ax,ax
   mov si,ax

   mov ss,ax
   mov ax,0x800
   mov sp,ax

; JMP NEAR
test_001:
    mov si,0x1
    jmp test_001a_ok
    hlt
test_001a_ok:

; JMP FAR
test_003:
    mov si,0x3
    jmp far test_003_ok
    hlt
    hlt
    hlt
    resb 70000
    hlt
    hlt
    hlt
test_003_ok:
    nop
   mov ax,0xa5ee
   mov si,ax
   hlt


This results in:

$ nasm -f bin jmp_call_ret_0.asm
jmp_call_ret_0.asm:20: error: binary output format does not support segment base references
jmp_call_ret_0.asm:24: warning: uninitialized space declared in .text section: zeroing [-w+zeroing]

I'm using nasm 2.16.01 as found in ubuntu

Any hints?

regards

p.s. yes this has been discussed on stackoverflow as well only the solutions there were work-arounds and I'm hoping to find a solution here to make it work without any trickery

Frank Kotler:
See if this helps:

https://www.nasm.us/xdoc/2.16.02rc1/html/nasmdoc8.html#section-8.1.

Best,
Frank

Folkert van Heusden:

--- Quote from: Frank Kotler on July 03, 2023, 08:39:34 AM ---See if this helps:

https://www.nasm.us/xdoc/2.16.02rc1/html/nasmdoc8.html#section-8.1.

Best,
Frank

--- End quote ---

Unfortunately not.

fredericopissarra:
In 16 bits mode (real mode) you cannot have more then 64 KiB in a single segment. Since you are not creating an EXE file, you cannot:

1 - Jump to another "segment" (there's only one);
2 - Declare uninitialized data (resb);
3 - Do a direct far jump or call...

This will compile, but will create the wrong code:

--- Code: ---  org 0x800

  xor ax,ax
  mov si,ax

  mov ss,ax
  mov ax,0x800
  mov sp,ax

  mov [jmp_addr+2],cs

; JMP NEAR
test_001:
  mov si,0x1
  jmp test_001a_ok
  hlt

jmp_addr:
  dw  test_003_ok
  dw  0

test_001a_ok:

; JMP FAR
test_003:
  mov si,0x3
  jmp far [jmp_addr]
  hlt
  hlt
  hlt
  times 70000 nop
  hlt
  hlt
  hlt
test_003_ok:
  nop
  mov ax,0xa5ee
  mov si,ax
  hlt
--- End code ---
Because that times 70000 nop will get you an image bigger than 64 KiB, so test_003_ok will be a reference inside your code segment (not outside)... test_003_ok will be offset 0x1_1196. but the offset reference in jmp_addr will be 0x1196, thus, wrong!

You can use 386 instructions in real mode and "normalize" the "physical address" like this:

--- Code: ---  ...
  mov eax,test_003_ok  ; this will be a 32 bits offset.
  mov bx,cs
  movzx ebx,bx
  shl ebx,4
  add eax,ebx  ; EAX has the "physical address" of test_003_ok.
  mov ebx,eax
  and ax,0x0f
  shr ebx,4      ; BX:AX is now the logical "normzlized" address of test_003_ok

  mov [jmp_addr],ax
  mov [jmp_addr+2],bx
  jmp far [jmp_addr]

jmp_addr:
  dw 0, 0
...
--- End code ---

Notice you'll have to calculate seg:offset to access anything beyond the first segment. (and I don't know if this will work with a .COM file no MS-DOS, for example).

Deskman243:
This question is pretty intriguing to me as I had to make a good amount of posts here to try and answer this. Currently what I understand is that x86-16 is based on 8086 processors. Now the design itself is built on a certain amount of data lines as previously mentioned

--- Quote ---In 16 bits mode (real mode) you cannot have more then 64 KiB in a single segment.

--- End quote ---
This is because the logical address is built from the A20 data lines. This clarifies the A1-16 controls for the standard segmentation for these programs. Now the meaning of the rest of the lines infers the area passed 64kb (0xFFFF + 1 =64kb and 0xFFFFF + 1 = 1 MB).  What I'm trying to get is whether these segments > 0x0FFFF are reserved in a way or more of a reserve for say one type of thing.


--- Quote ---Notice you'll have to calculate seg:offset to access anything beyond the first segment.

--- End quote ---

My previous post was on how data is accessed by these segments because I could only ever get data reference passed 64kb. Other than that I was researching disk reading to perhaps get an answer on the correlated links below.

Adjusting segments for linux linker commands and build files
https://forum.nasm.us/index.php?topic=3881.0

Disk Routines under NASM
https://forum.nasm.us/index.php?topic=3884.0

Navigation

[0] Message Index

[#] Next page

Go to full version