Let's say I have some code like this:
_TEXT16 SEGMENT USE16 'CODE'
_start:
; some code...
; add padding
byte 512-($-_start) dup (0) ; works fine
_TEXT16 ENDS
_TEXT32 SEGMENT USE32 'CODE'
; some code
byte 1024-($-_start) dup (0) ; error A2192: Operands must be in same segment
_TEXT32 ENDS
In NASM you would just do something like this times 1024-($-$$) db 0
, but unfortunately the $$
is not supported in MASM or in JWASM, which is what I'm using at the moment. I need this to align the blocks of my bootloader to the size of readable disk sectors.
So, my question is, how do I add padding of 512 bytes to my code blocks in MASM?
Edit:
The scenario has changed a bit.
_TEXT16 SEGMENT USE16 'CODE'
_start:
; some code...
_TEXT16 ENDS
_TEXT32 SEGMENT USE32 'CODE'
; some code
_TEXT32 ENDS
_TEXT64 SEGMENT USE64 'CODE'
; some code
; add padding
byte 510-($-_start) dup (0) ; error A2192: Operands must be in same segment
dw 0AA55h
_TEXT64 ENDS
Now how would I go about adding the correct padding here?
CodePudding user response:
Ok, this is a difficult one to explain but I finally solved my problem.
The code that ended up working was this:
.386P
.model TINY, C
_TEXT16 SEGMENT BYTE USE16 'CODE'
org 07C00h
begin16:
_start:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov bp, 07C00h
mov sp, bp
mov ah, 0Eh
mov al, 'A'
mov bl, 0Fh
int 10h
cli
hlt
end16:
size16 equ end16 - begin16
_TEXT16 ENDS
_TEXT32 SEGMENT BYTE USE32 'CODE'
begin32:
start_protected_mode:
cli
hlt
end32:
size32 equ end32 - begin32
_TEXT32 ENDS
.x64
_TEXT64 SEGMENT BYTE USE64 'CODE'
begin64:
start_long_mode:
cli
hlt
end64:
size64 equ end64 - begin64
_TEXT64 ENDS
_BOOTDATA SEGMENT BYTE 'DATA'
begin_data:
bootDisk db ?
end_data:
size_data equ end_data - begin_data
_BOOTDATA ENDS
_PADDING SEGMENT BYTE
org (510 - size16 - size32 - size64 - size_data) ; either of these work
;byte (510 - size16 - size32 - size64 - size_data) dup(0) ; either of these work
dw 0AA55h
_PADDING ENDS
END _start
What's happening here is as follows. The first org
directive (org 07C00h
) sets the starting address of the program. It only does that because we have told it with the use of the END
directive, that we have given a label to the start of our code (END _start
). If you don't give the END
directive a stating label of your code, the first org
directive will just be resolved as a lot of zeros prepending your actual code. Or in short, it will actually offset your code by whatever value you give it.
The second org
directive (org org (510 - size16 - size32 - size64 - size_data)
) however acts like an offset, even if you don't give a label to the END
directive.
Taking all of that into consideration and our result looks like this:
00000000 33C0 xor ax,ax
00000002 8ED8 mov ds,ax
00000004 8EC0 mov es,ax
00000006 8ED0 mov ss,ax
00000008 BD007C mov bp,0x7c00
0000000B 8BE5 mov sp,bp
0000000D B40E mov ah,0xe
0000000F B041 mov al,0x41
00000011 B30F mov bl,0xf
00000013 CD10 int 0x10
00000015 FA cli
00000016 F4 hlt
00000017 FA cli
00000018 F4 hlt
00000019 FA cli
0000001A F4 hlt
0000001B 0000 add [bx si],al
0000001D 0000 add [bx si],al
0000001F 0000 add [bx si],al
00000021 0000 add [bx si],al
00000023 0000 add [bx si],al
00000025 0000 add [bx si],al
00000027 0000 add [bx si],al
00000029 0000 add [bx si],al
0000002B 0000 add [bx si],al
0000002D 0000 add [bx si],al
0000002F 0000 add [bx si],al
00000031 0000 add [bx si],al
00000033 0000 add [bx si],al
00000035 0000 add [bx si],al
00000037 0000 add [bx si],al
00000039 0000 add [bx si],al
0000003B 0000 add [bx si],al
0000003D 0000 add [bx si],al
0000003F 0000 add [bx si],al
00000041 0000 add [bx si],al
00000043 0000 add [bx si],al
00000045 0000 add [bx si],al
00000047 0000 add [bx si],al
00000049 0000 add [bx si],al
0000004B 0000 add [bx si],al
0000004D 0000 add [bx si],al
0000004F 0000 add [bx si],al
00000051 0000 add [bx si],al
00000053 0000 add [bx si],al
00000055 0000 add [bx si],al
00000057 0000 add [bx si],al
00000059 0000 add [bx si],al
0000005B 0000 add [bx si],al
0000005D 0000 add [bx si],al
0000005F 0000 add [bx si],al
00000061 0000 add [bx si],al
00000063 0000 add [bx si],al
00000065 0000 add [bx si],al
00000067 0000 add [bx si],al
00000069 0000 add [bx si],al
0000006B 0000 add [bx si],al
0000006D 0000 add [bx si],al
0000006F 0000 add [bx si],al
00000071 0000 add [bx si],al
00000073 0000 add [bx si],al
00000075 0000 add [bx si],al
00000077 0000 add [bx si],al
00000079 0000 add [bx si],al
0000007B 0000 add [bx si],al
0000007D 0000 add [bx si],al
0000007F 0000 add [bx si],al
00000081 0000 add [bx si],al
00000083 0000 add [bx si],al
00000085 0000 add [bx si],al
00000087 0000 add [bx si],al
00000089 0000 add [bx si],al
0000008B 0000 add [bx si],al
0000008D 0000 add [bx si],al
0000008F 0000 add [bx si],al
00000091 0000 add [bx si],al
00000093 0000 add [bx si],al
00000095 0000 add [bx si],al
00000097 0000 add [bx si],al
00000099 0000 add [bx si],al
0000009B 0000 add [bx si],al
0000009D 0000 add [bx si],al
0000009F 0000 add [bx si],al
000000A1 0000 add [bx si],al
000000A3 0000 add [bx si],al
000000A5 0000 add [bx si],al
000000A7 0000 add [bx si],al
000000A9 0000 add [bx si],al
000000AB 0000 add [bx si],al
000000AD 0000 add [bx si],al
000000AF 0000 add [bx si],al
000000B1 0000 add [bx si],al
000000B3 0000 add [bx si],al
000000B5 0000 add [bx si],al
000000B7 0000 add [bx si],al
000000B9 0000 add [bx si],al
000000BB 0000 add [bx si],al
000000BD 0000 add [bx si],al
000000BF 0000 add [bx si],al
000000C1 0000 add [bx si],al
000000C3 0000 add [bx si],al
000000C5 0000 add [bx si],al
000000C7 0000 add [bx si],al
000000C9 0000 add [bx si],al
000000CB 0000 add [bx si],al
000000CD 0000 add [bx si],al
000000CF 0000 add [bx si],al
000000D1 0000 add [bx si],al
000000D3 0000 add [bx si],al
000000D5 0000 add [bx si],al
000000D7 0000 add [bx si],al
000000D9 0000 add [bx si],al
000000DB 0000 add [bx si],al
000000DD 0000 add [bx si],al
000000DF 0000 add [bx si],al
000000E1 0000 add [bx si],al
000000E3 0000 add [bx si],al
000000E5 0000 add [bx si],al
000000E7 0000 add [bx si],al
000000E9 0000 add [bx si],al
000000EB 0000 add [bx si],al
000000ED 0000 add [bx si],al
000000EF 0000 add [bx si],al
000000F1 0000 add [bx si],al
000000F3 0000 add [bx si],al
000000F5 0000 add [bx si],al
000000F7 0000 add [bx si],al
000000F9 0000 add [bx si],al
000000FB 0000 add [bx si],al
000000FD 0000 add [bx si],al
000000FF 0000 add [bx si],al
00000101 0000 add [bx si],al
00000103 0000 add [bx si],al
00000105 0000 add [bx si],al
00000107 0000 add [bx si],al
00000109 0000 add [bx si],al
0000010B 0000 add [bx si],al
0000010D 0000 add [bx si],al
0000010F 0000 add [bx si],al
00000111 0000 add [bx si],al
00000113 0000 add [bx si],al
00000115 0000 add [bx si],al
00000117 0000 add [bx si],al
00000119 0000 add [bx si],al
0000011B 0000 add [bx si],al
0000011D 0000 add [bx si],al
0000011F 0000 add [bx si],al
00000121 0000 add [bx si],al
00000123 0000 add [bx si],al
00000125 0000 add [bx si],al
00000127 0000 add [bx si],al
00000129 0000 add [bx si],al
0000012B 0000 add [bx si],al
0000012D 0000 add [bx si],al
0000012F 0000 add [bx si],al
00000131 0000 add [bx si],al
00000133 0000 add [bx si],al
00000135 0000 add [bx si],al
00000137 0000 add [bx si],al
00000139 0000 add [bx si],al
0000013B 0000 add [bx si],al
0000013D 0000 add [bx si],al
0000013F 0000 add [bx si],al
00000141 0000 add [bx si],al
00000143 0000 add [bx si],al
00000145 0000 add [bx si],al
00000147 0000 add [bx si],al
00000149 0000 add [bx si],al
0000014B 0000 add [bx si],al
0000014D 0000 add [bx si],al
0000014F 0000 add [bx si],al
00000151 0000 add [bx si],al
00000153 0000 add [bx si],al
00000155 0000 add [bx si],al
00000157 0000 add [bx si],al
00000159 0000 add [bx si],al
0000015B 0000 add [bx si],al
0000015D 0000 add [bx si],al
0000015F 0000 add [bx si],al
00000161 0000 add [bx si],al
00000163 0000 add [bx si],al
00000165 0000 add [bx si],al
00000167 0000 add [bx si],al
00000169 0000 add [bx si],al
0000016B 0000 add [bx si],al
0000016D 0000 add [bx si],al
0000016F 0000 add [bx si],al
00000171 0000 add [bx si],al
00000173 0000 add [bx si],al
00000175 0000 add [bx si],al
00000177 0000 add [bx si],al
00000179 0000 add [bx si],al
0000017B 0000 add [bx si],al
0000017D 0000 add [bx si],al
0000017F 0000 add [bx si],al
00000181 0000 add [bx si],al
00000183 0000 add [bx si],al
00000185 0000 add [bx si],al
00000187 0000 add [bx si],al
00000189 0000 add [bx si],al
0000018B 0000 add [bx si],al
0000018D 0000 add [bx si],al
0000018F 0000 add [bx si],al
00000191 0000 add [bx si],al
00000193 0000 add [bx si],al
00000195 0000 add [bx si],al
00000197 0000 add [bx si],al
00000199 0000 add [bx si],al
0000019B 0000 add [bx si],al
0000019D 0000 add [bx si],al
0000019F 0000 add [bx si],al
000001A1 0000 add [bx si],al
000001A3 0000 add [bx si],al
000001A5 0000 add [bx si],al
000001A7 0000 add [bx si],al
000001A9 0000 add [bx si],al
000001AB 0000 add [bx si],al
000001AD 0000 add [bx si],al
000001AF 0000 add [bx si],al
000001B1 0000 add [bx si],al
000001B3 0000 add [bx si],al
000001B5 0000 add [bx si],al
000001B7 0000 add [bx si],al
000001B9 0000 add [bx si],al
000001BB 0000 add [bx si],al
000001BD 0000 add [bx si],al
000001BF 0000 add [bx si],al
000001C1 0000 add [bx si],al
000001C3 0000 add [bx si],al
000001C5 0000 add [bx si],al
000001C7 0000 add [bx si],al
000001C9 0000 add [bx si],al
000001CB 0000 add [bx si],al
000001CD 0000 add [bx si],al
000001CF 0000 add [bx si],al
000001D1 0000 add [bx si],al
000001D3 0000 add [bx si],al
000001D5 0000 add [bx si],al
000001D7 0000 add [bx si],al
000001D9 0000 add [bx si],al
000001DB 0000 add [bx si],al
000001DD 0000 add [bx si],al
000001DF 0000 add [bx si],al
000001E1 0000 add [bx si],al
000001E3 0000 add [bx si],al
000001E5 0000 add [bx si],al
000001E7 0000 add [bx si],al
000001E9 0000 add [bx si],al
000001EB 0000 add [bx si],al
000001ED 0000 add [bx si],al
000001EF 0000 add [bx si],al
000001F1 0000 add [bx si],al
000001F3 0000 add [bx si],al
000001F5 0000 add [bx si],al
000001F7 0000 add [bx si],al
000001F9 0000 add [bx si],al
000001FB 0000 add [bx si],al
000001FD 0055AA add [di-0x56],dl
As you can see I had to calculate the size of each segment by using labels at the beginning and end of it. I then set some constants to those sizes. If you ask yourself, why didn't I just put one label at the start and one at the end of my code? Then I have to tell you, that you can only put labels in segments and can only access them from within the same segment. Hence the constants, calculating the sizes for each one.
So in conclusion:
- The first
org
sets the program offset if you giveEND
a label to the start of your code - All following
org
directives will act as offsets, no matter what - Align your
SEGMENT
s toBYTE
s - And do some constant label calculation hackery to get the right offset
Please don't completely take my word for this. This is only the result of many tests. If you have questions, please feel free to comment.
Otherwise, I hope that this helps whoever finds this.
CodePudding user response:
Perhaps use org 510
or org 510 7C00h
to seek to that point?
NASM's docs specifically mention that NASM doesn't support the kind of trickery MASM's org
directive allows, which implies that MASM's org
is usable for this. The NASM docs even show a MASM example:
; MASM example from the NASM manual
ORG 0
; some boot sector code
ORG 510
DW 0xAA55
I don't know how this might interact with multiple segments. The OP reports that this only works with both org
directives inside the same segment. Perhaps there's a way to specify an origin for a segment as part of declaring it?
Or perhaps another option, can you ask MASM to calculate the size of those earlier segments in the case where you're not padding them to fixed sizes? (When the sizes are fixed, things are obviously simple: you just make the second segment 512 bytes, following the first 512-byte segment, so it will end at 1024.)
Like byte 510 - sizeof _TEXT16 -($-_start) dup (0)
or something like that to also subtract the lengths of the previous segments? I have no idea if MASM allows that. Apparently that doesn't work, so perhaps define an equ
or size16 = $-start16
or something inside each of the two earlier segments.
Either way that wouldn't account for padding between segments, if there is any to align their starts.
Or of course you could always append a boot signature to the assembler's flat binary output separately, as part of the build process, if you can't figure out how to get the assembler to do it for you.
In a Linux shell, this command opens boot.bin
, seeks to byte 510, and writes db 0x55, 0xaa
echo -ne '\x55\xAA' | dd of=boot.bin conv=notrunc bs=2 count=1 seek=$((510/2))
If you're stuck using Windows, there is port of dd
, for example http://www.chrysocome.net/downloads/dd-0.6beta3.src.zip If you aren't using a shell like bash
or zsh
to expand $((510/2))
, that's just seek=255
because dd
takes seeks as a number of blocks, not bytes. And I don't know how to pipe arbitrary binary data on Windows; perhaps with python
if you have it installed, or just create a 2-byte file using an assembler.
dd.exe if=aa55.bin of=boot.bin conv=notrunc bs=2 count=1 seek=255