I had been trying to replicate an example from FASM (flat assembler) to NASM but I had not been able to do it and I try to understand the way NASM handles segments (sections).
ormat mz
entry main:start
stack 100h
segment main
start:
mov ax, text
mov ds, ax
mov dx, hello
call extra:write_text
mov ax, 4c00h
int 21h
segment text
hello db 'Hello world!', 24h
segment extra
write_text:
mov ah, 9
int 21h
retf
FASM generates a MSDOS exe file and loading this in DEBUG I see the following:
0D9D:0000 B89F0D MOV AX,0D9F
0D9D:0003 8ED8 MOV DS,AX
0D9D:0005 BA0000 MOV DX,0000
0D9D:0008 9A0000A00D CALL 0DA0:0000
0D9D:000D B8004C MOV AX,4C00
0D9D:0010 CD21 INT 21
As you may see, FASM creates the segment and set the CALL as a far call. extra is effectively placed in a separate segment. The data segment is in a separate segment as well.
I tried doing this example in NASM:
section code
..start:
mov ax, seg hello
mov ds, ax
mov dx, hello
call extra:write_text
mov ax, 4c00h
int 21h
section data
hello db "Hello World!", 24h
section extra
write_text:
mov ah, 9
int 21h
retf
section stack class=stack
resb 100h
And linking with wlink using this link file:
system dos
option map
name seg2.exe
file seg2.obj
The generated code is different:
0D9D:0000 B89D0D MOV AX,0D9D
0D9D:0003 8ED8 MOV DS,AX
0D9D:0005 BA1200 MOV DX,0012
0D9D:0008 9A1F009D0D CALL 0D9D:001F
0D9D:000D B8004C MOV AX,4C00
0D9D:0010 CD21 INT 21
0D9D:0012 48 DEC AX
0D9D:0013 65 GS: (unused)
0D9D:0014 6C INSB
0D9D:0015 6C INSB
0D9D:0016 6F OUTSW
0D9D:0017 20576F AND [BX 6F],DL
0D9D:001A 726C JB 0088
0D9D:001C 642124 AND FS:[SI],SP
0D9D:001F B409 MOV AH,09
As you may see, write_text is in the same segment as the rest of the code (and apparently the data segment as well) but it was not put in a separate segment as I thought.
Am I missing something here? Is there any way to actually place code in a separate segment? Any help, guidance or explanation of what is happening or how to achieve such would be appreciated!
and yes, I tried in MASM and the same thing happens, is FASM the only one with that super power?
Thanks!
CodePudding user response:
What you want is a support for memory models, which NASM lacks, it treats intersegment transfers as NEAR and the programmer is responsible for coding CALL FAR instructions where necessary.
No, FASM is not the only assembler aware of memory models. Here is your program tailored for €ASM
| |seg4 PROGRAM Format=MZ,Model=LARGE,Entry=start
|[main] |[main] SEGMENT Purpose=CODE
|0000: |start:
|0000:B8{0000} | mov ax,PARA# [text]
|0003:8ED8 | mov ds, ax
|0005:BA[0000] | mov dx, hello
|0008:9A[0000]{0000} | call write_text
|000D:B8004C | mov ax, 4c00h
|0010:CD21 | int 21h
|0012: |
|[text] |[text] segment Purpose=DATA
|0000:48656C6C6F20776F726C~| hello db 'Hello world!', 24h
|[extra] |[extra] segment Purpose=CODE
|0000: |write_text:
|0000:B409 | mov ah, 9
|0002:CD21 | int 21h
|0004:CB | retf
|[stack] |[stack] SEGMENT Purpose=STACK
|0000:....................~| DW 100h * BYTE
| | ENDPROGRAM
| **** ListMap "seg4.exe",groups=4,segments=4,entry=[main]:00000000h,stack=[stack]:00000100h
| [main],RVA=00000000h,size=00000012h=18,group [main]
| [main],RVA=00000000h,size=00000012h=18,width=16,align=0010h,purpose=CODE
| [text],RVA=00000020h,size=0000000Dh=13,group [text]
| [text],RVA=00000020h,size=0000000Dh=13,width=16,align=0010h,purpose=DATA
| [extra],RVA=00000030h,size=00000005h=5,group [extra]
| [extra],RVA=00000030h,size=00000005h=5,width=16,align=0010h,purpose=CODE
| [stack],RVA=00000040h,size=00000100h=256,group [stack]
| [stack],RVA=00000040h,size=00000100h=256,width=16,align=0010h,purpose=STACK