flat assembler
Message board for the users of flat assembler.

Index > Windows > fasm 16bit 'and' instruction bug

Author
Thread Post new topic Reply to topic
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 03 Feb 2007, 15:24
I think I discovered a bug in fasm concerning the 16-bit 'and' instruction. when I remove the 'and ax, $100' everything works fine, but when it is un-commented 'CRASH'. see code below:
Code:
format PE CONSOLE
entry MAIN

include '%fasminc%\win32a.inc'
include '%fasminc%\equates\kernel32.inc'
include '%fasminc%\equates\gdi32.inc'
include '%fasminc%\equates\user32.inc'
include '%fasminc%\equates\shell32.inc'

section '.data' data readable writeable
  align 8
  number dq 3.1415926535897932

section '.code' code readable executable

proc MAIN
     ;invoke  GetCommandLine
     ;invoke  CommandLineToArgvW(lpCmdLine, int *pNumArgs)
     use16
     mov     ax, $1a00
     int     $2f
     and     ax, $100  <- [RIGHT HERE]
     use32
     .if     ax = 0
             cinvoke printf, "ANSI.SYS installed."
     .else
             cinvoke printf, "ANSI.SYS not installed."
     .endif

     ;cinvoke printf, "Value: %1.16f", double [number]
     call    WaitKey
     invoke  ExitProcess, 0
     return
endp

proc WaitKey
     cinvoke printf, <10,13,"[Press ESC or SPACE to continue]",10,13>

     .repeat
             invoke  Sleep, 10
             invoke  GetAsyncKeyState, VK_ESCAPE
             push    eax
             invoke  GetAsyncKeyState, VK_SPACE
             pop     ecx
             or      eax, ecx
             and     eax, $8000
     .until  eax <> NULL
     return
endp

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL',\
          gdi32,'GDI32.DLL',\
          shell32,'SHELL32.DLL',\
          msvcrt, 'MSVCRT.DLL'

  include '%fasminc%\apia\kernel32.inc'
  include '%fasminc%\apia\user32.inc'
  include '%fasminc%\apia\gdi32.inc'
  include '%fasminc%\apia\shell32.inc'
  include '%fasminc%\apia\msvcrt.inc'
    
Post 03 Feb 2007, 15:24
View user's profile Send private message Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 03 Feb 2007, 15:51
This probably should've been in the 'compiler internals' forum, so if the moderator would like to move this, thank you.
Post 03 Feb 2007, 15:51
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 03 Feb 2007, 19:53
There might be better experts than me here in Confused Confused ... but I think this
code CANNOT work. Confused System requirements ? DOS ? Windoze ?
"use16" will switch FASM to 16-bit,
but your PE-32 executable still runs in 32-bit PM ... and the INT
probably won't get decoded and even less executed at all Sad

Quote:
should've been in the 'compiler internals'


I would move it to Main. DOS vs Windoze, 16-bit vs 32-bit issue. Wink

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 03 Feb 2007, 19:53
View user's profile Send private message Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 03 Feb 2007, 20:23
The code works just fine if I comment out the 'and ax, $100'. And as I look at the intel docs and try to hard code the instruction into the code, it still crashes at that instruction. So, I'm kind of wondering if it's really an fasm bug or not? Confused
Post 03 Feb 2007, 20:23
View user's profile Send private message Reply with quote
asmfan



Joined: 11 Aug 2006
Posts: 392
Location: Russian
asmfan 03 Feb 2007, 20:53
Oh, i see there some misunderstanding how code works under 32bit.
Code:
format PE CONSOLE    

means create 32bit (PE) console (itself) program. 16bit coded code (use 16) will be treated by OS as 32bit anyway, but without/with 66h prefix.

_________________
Any offers?
Post 03 Feb 2007, 20:53
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8357
Location: Kraków, Poland
Tomasz Grysztar 03 Feb 2007, 21:17
First of all: interrupt functions like INT 2Fh you tried to use don't work in the PE programs, and they will crash your program (the exception are VxD calls by INT 20h in Win9x, but that's a really different story...). The only reason why it did not crash your program is because you have combined it with another serious mistake. I will try to explain in detail.

The USE16 makes assembler generate 16-bit code, however whether the code is interpreted by processor as 16-bit or 32-bit one, it is dependend on the settings of code segment. In Win32 code segment is 32-bit one, and even if you make fasm to generate some code as 16-bit one, the processor will interprete it as 32-bit one, most probably causing a serious trouble.

The 66h prefix switches the size of data on which instructions operators, from the default for current mode to the opposite one. In 16-bit mode the 16-bit size is default, and thus prefixing an instruction with 66h makes it work on 32-bit operands. Example:

In 16-bit mode:
B8 00 1A - MOV AX,1A00h
66 B8 00 1A 00 00 - MOV EAX,00001A00h

In 32-bit mode:
B8 00 1A 00 00 - MOV EAX,00001A00h
66 B8 00 1A - MOV AX,1A00h

So now when you tell fasm to generate code for 16-bit mode and put there a "mov ax,1A00h" instruction, it will generate the three bytes B8 00 1A. However in PE program the code is always executes as 32-bit. Thus when processor sees the B8 instruction opcode without any prefix, it takes it as "mov eax,..." instruction. However this instruction needs two bytes more for the 32-bit constant that has to be stored in EAX! And so it executes the instruction that takes five bytes in total, not three. And, by coincidence, the two bytes that follow the three bytes B8 00 1A in your code are CD 2F - the "int 2Fh" instruction. So processor executes the "mov eax,2FCD1A00h" instruction, and goes to what follows. Thus if you had only this in your USE16 block, there was nothing wrong with it, the interrupt wasn't just called at all.

But when you added another instruction encoded for 16-bit mode, it again are two more bytes when was executed in 32-bit mode, and this time it caused the instruction chain that follows to become completely broken. Thus this crash.

I hope I was able to explain it clearly, if you still don't understand something, please let me know.
Post 03 Feb 2007, 21:17
View user's profile Send private message Visit poster's website Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 03 Feb 2007, 23:05
Yeh, I think I do, when compiled, fasm compiled it correctly as 16-bit, but when exectuted, it still tried to run as 32-bit. So I guess I would have to make it a .com file wouldn't I?
Post 03 Feb 2007, 23:05
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 04 Feb 2007, 06:50
Quote:
So I guess I would have to make it a .com file wouldn't I?


Right. If you want to:

- Use DOS INT's
or
- Expose use16 FASM bugs (this is NOT one)

you have to use

- format MZ
or
- format binary as "COM"

And run it preferably in DOS ...

You can also disassemble your code with use32, and you'll
see the garbage the CPU has to execute, and no INT instruction at all Shocked

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 04 Feb 2007, 06:50
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.