Page 1 of 2
Nasm syntax problem
Posted: Tue Jun 18, 2013 11:51 am
by computertrick
Hi this is likely a noobie question but how come this code does not work
Code: Select all
TEST dd 0x00
TEST2 dd 0x00
mov dword[TEST], [TEST2]
Thats just a basic example. How come I can't move data directly why must it be put into registers first
Re: Nasm syntax problem
Posted: Tue Jun 18, 2013 11:54 am
by HugeCode
Because x86 instructions can have only one displacement. The instruction set is designed so.
Re: Nasm syntax problem
Posted: Tue Jun 18, 2013 11:55 am
by computertrick
I'm trying not to write dirty code that's why I asked. Can anyone see anything in my code that should be done differently
Code: Select all
org 0 ; we start everything at zero
jmp start
MANU_DESC db 'mkdosfs '
BLOCK_SIZE dw 512
BLOCKS_PER_ALLOCATION_UNIT db 128
RESERVED_BLOCKS dw 1
TOTAL_FATS db 1
TOTAL_ROOT_ENTRIES dw 512
TOTAL_BLOCKS dw 0xffff
MEDIA_DESCRIPTOR db 0xf8
BLOCKS_PER_FAT dw 0x01
BLOCKS_PER_TRACK dw 18
TOTAL_HEADS dw 0x02
HIDDEN_BLOCKS dd 0x00
TOTAL_BLOCKS_2 dd 0x00
DRIVE_NUMBER dw 0x00
EXTENDED_BOOT_SIGNATURE db 0x29
VOLUME_SERIAL_NUMBER dd 0x9d86f18c
VOLUME_LABEL db 'SEAGULL '
FILE_SYSTEM_IDENTIFIER db 'FAT16 '
; Calculated in memory
ROOT_DIRECTORY dd 0x00
DAPACK:
db 0x10
db 0
.len: dw 1
.loc: dd 0x7e00
.sec: dd 2
dd 0
start:
mov ax, 0x7c0
mov ds, ax
mov es, ax
mov sp, 0x1000
mov bp, 0
mov ss, bp
; Root Directory Logical Sector = (TOTAL_FATS * BLOCKS_PER_FAT) + (RESERVED_BLOCKS)
mov ax, [TOTAL_FATS]
mul word [BLOCKS_PER_FAT]
mov word [ROOT_DIRECTORY+2], dx
push dx
add ax, [RESERVED_BLOCKS]
mov word [ROOT_DIRECTORY], ax
; Load root directory
mov word [DAPACK.sec], ax
pop dx
mov word [DAPACK.sec+2], dx
mov si, DAPACK ; address of "disk address packet"
mov ah, 0x42 ; AL is unused
mov dl, 0x80 ; drive number 0 (OR the drive # with 0x80)
int 0x13
jc err
mov si, 512
mov bx, 40
call print_until
jmp $
err:
mov si, ERROR
call print
jmp $
print:
pusha
mov ah, 0eh
.repeat:
lodsb
cmp al, 0
je .done
int 10h
jmp .repeat
.done:
popa
ret
print_until:
mov ah, 0eh
.repeat:
lodsb
cmp bx, 0
je .done
int 10h
dec bx
jmp .repeat
.done:
popa
ret
ERROR db "Failed to load sector", 10, 13, 0
times 510-($-$$) db 0 ; fill in the remaining space with zero
dw 0xaa55 ; legacy boot signature
Re: Nasm syntax problem
Posted: Tue Jun 18, 2013 10:42 pm
by HugeCode
Are you getting some error output?
Re: Nasm syntax problem
Posted: Tue Jun 18, 2013 11:11 pm
by Antti
Code: Select all
start:
mov ax, 0x7c0
mov ds, ax
mov es, ax
mov sp, 0x1000
mov bp, 0 ; <----- Critical point
mov ss, bp
It is dangerous to change just the SP and let interrupts be enabled. There a couple of ways to solve this. Maybe this is most easiest to understand:
Code: Select all
start:
jmp 0x7c0:update_cs
update_cs:
mov ax, 0x7c0
mov ds, ax
mov es, ax
cli
mov sp, 0x1000
mov bp, 0
mov ss, bp
sti
I also updated CS to be equal with ES and DS. I did not check more of your code.
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 1:10 am
by Combuster
org 0
jmp start
MANU_DESC db 'mkdosfs '
How many bytes is a jump? 2? 3? 5? How many bytes should exist between the start of the sector and the OEM field?
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 5:47 am
by computertrick
jmp start allocates 3 bytes this can't change or it will damage my FAT format
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 6:10 am
by Prochamber
Here's the problem: Optimizations.
When the context is not specific and optimizations are enabled, NASM will try to generate the smallest and/or fastest instruction possible. The maximum level of optimization is enabled
by default. Your initial jump must occupy
three bytes or it will break the file system.
So, unless you disable optimizations or specify the length of your jump NASM will compile this as the smallest possible jump, which is a
two byte jump. I recommend you either
a) Be more specific (recommended)
OR
b) Assemble with the -O0 flag to disable optimizations.
By the way, if you want to do memory to memory moves, you could use the
movs instruction. This copies a byte,
word or double word from DS:SI to ES:DI and increases both SI and DI if the carry flag is cleared. Otherwise they are decreased.
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 6:37 am
by Combuster
Or you can just make sure there's three bytes regardless of what your assembler tries.
Code: Select all
start: JMP loader
TIMES 0Bh-$+start DB 0
bpbBytesPerSector: DW 512
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 7:12 am
by Minoto
Prochamber wrote:By the way, if you want to do memory to memory moves, you could use the
movs instruction. This copies a byte,
word or double word from DS:SI to ES:DI and increases both SI and DI if the carry flag is cleared. Otherwise they are decreased.
I believe you meant the direction flag, not the carry flag.
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 8:35 am
by computertrick
Prochamber wrote:Here's the problem: Optimizations.
When the context is not specific and optimizations are enabled, NASM will try to generate the smallest and/or fastest instruction possible. The maximum level of optimization is enabled
by default. Your initial jump must occupy
three bytes or it will break the file system.
So, unless you disable optimizations or specify the length of your jump NASM will compile this as the smallest possible jump, which is a
two byte jump. I recommend you either
a) Be more specific (recommended)
OR
b) Assemble with the -O0 flag to disable optimizations.
By the way, if you want to do memory to memory moves, you could use the
movs instruction. This copies a byte,
word or double word from DS:SI to ES:DI and increases both SI and DI if the carry flag is cleared. Otherwise they are decreased.
Hi thanks for your response, When I look at the hex code the jump has allocated 3 bytes and the file system works fine
Re: Nasm syntax problem
Posted: Wed Jun 19, 2013 4:50 pm
by Prochamber
Are you sure? When I compiled your code with the latest version of NASM, ndisasm shows the first instruction being a two byte 'short' jump with no intervention. This is followed directly by the OEM identifier.
Re: Nasm syntax problem
Posted: Sun Jun 23, 2013 1:17 pm
by computertrick
Prochamber wrote:Are you sure? When I compiled your code with the latest version of NASM, ndisasm shows the first instruction being a two byte 'short' jump with no intervention. This is followed directly by the OEM identifier.
Yes I am sure because both windows and linux can recognize the file system and it runs fine in qemu. But I am not 100% sure I have the latest version of nasm so I will modify the JMP just to take precautions cheers for letting me know about that
Re: Nasm syntax problem
Posted: Sun Jun 23, 2013 4:43 pm
by Prochamber
If you have a version before 0.98 optimisations are not enabled by default, but they are for newer version.
There's not much more to improve, however you could use CX instead of BX to specify the number of bytes to print in "print_until" then you could use the
Loop instruction to shave a few bytes off.
Code: Select all
print_until:
pusha
mov ah, 0Eh
.repeat:
lodsb
int 10h
loop .repeat
popa
ret
Your routine actually looses the stack because it uses popa without pusha.
You should clear interrupt before changing the stack pointer and segment then restore them afterwards.
Re: Nasm syntax problem
Posted: Sun Jun 23, 2013 8:37 pm
by gerryg400
You should clear interrupt before changing the stack pointer and segment then restore them afterwards.
It's not necessary to disable interrupts if the SS is loaded first. The processor does it for you automatically.
The Intel manual wrote:Loading the SS register with a MOV instruction inhibits all interrupts until after the execution of the next instruction. This operation allows a stack pointer to be loaded into the ESP register with the next instruction (MOV ESP, stack-pointer value) before an interrupt occurs1. Be aware that the LSS instruction offers a more efficient method of loading the SS and ESP registers.