flat assembler
Message board for the users of flat assembler.

flat assembler > Main > is there any directive like the [cpu 8086]?

Author
Thread Post new topic Reply to topic
hckr83



Joined: 12 Nov 2006
Posts: 86
Location: usa
I have recently decided to switch to fasm(hooray for you) and well before I had used nasm...I have read and got the bits16, so now..is there any directive to make only 8086 code, much like how the [cpu 8086] worked in nasm

I am switching because of how horribly supported nasm is recently...
plus when using the [cpu 8086] directive in it, it produces inaccurate 16bit jumps

[edit]
for those of you who found this thread with searching, see http://board.flatassembler.net/topic.php?t=6921

_________________
x86 CPU Emulation library: http://sourceforge.net/projects/x86lib
Post 10 Feb 2007, 05:13
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904
Quote:
I have recently decided to switch to fasm(hooray for you)


Smile

Quote:
is there any directive to make only 8086 code, much like how the [cpu 8086] worked in nasm


You probably hit a weak point of FASM, I also wanted to ask this. Confused

MA$M has

Code:
.386
    


There should be a directive like cpu 8086 (+ 80286, 80386,
80486, P1, P2, P3), resulting in an error when discovering an unsupported
instrucion, like BSWAP after cpu 80386

http://nasm.sourceforge.net/doc/html/nasmdocb.html

FASM.TXT unfortunately boasts with all instructions without
mentioning the risks (minimal CPU, privileged).

_________________
Bug Nr.: 12345

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

Status: Closed: NOT a Bug
Post 10 Feb 2007, 06:16
View user's profile Send private message Reply with quote
asmfan



Joined: 11 Aug 2006
Posts: 401
Location: Russian
I think it's good idea too - it would be useful to limit automatically allowed instruction - say i want instructions for CPU with SSE2 support only and if i occasionally use some older instruction (SSE3, SSSE3) fasm could prompted me an error.
Post 10 Feb 2007, 09:45
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7300
Location: Kraków, Poland
While with 8086/286/386 it was quite simple and straightforward, with more modern instructions sets that are often just turned on or off by a feature bits etc. it would be a more trouble than it is worth (in my opinion).
fasm generally tries to go for the totality of instruction set (note the undocumented "loadall286" and "loadall386" mnemonic), which also saves you a trouble when implementing routine variants for various processors within the single source.

As for the 8086 programming, in the early days of fasm I proposed sometimes an 8086.INC file that looked like:
Code:
je equ short je
jb equ short jb
; ...and so on for all conditional jumps

macro shr val,cnt { times cnt: shr val,1 }
macro shl val,cnt { times cnt: shl val,1 }
; ...and so on for all shift instructions    

to perform TASM-like conversion of code from higher processors to 8086 (not counting the instructions that are completely unsupported, that's a different story).
Post 10 Feb 2007, 12:32
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
Tomasz Grysztar wrote:
While with 8086/286/386 it was quite simple and straightforward, with more modern instructions sets that are often just turned on or off by a feature bits etc. it would be a more trouble than it is worth (in my opinion).
fasm generally tries to go for the totality of instruction set (note the undocumented "loadall286" and "loadall386" mnemonic), which also saves you a trouble when implementing routine variants for various processors within the single source.

As for the 8086 programming, in the early days of fasm I proposed sometimes an 8086.INC file that looked like:
Code:
je equ short je
jb equ short jb
; ...and so on for all conditional jumps

macro shr val,cnt { times cnt: shr val,1 }
macro shl val,cnt { times cnt: shl val,1 }
; ...and so on for all shift instructions    

to perform TASM-like conversion of code from higher processors to 8086 (not counting the instructions that are completely unsupported, that's a different story).

That wuld also be the way I would have suggested it.
Writing switches for every available x86 CPU-family and/or model would just overbloat fasm, so writing macros for each instruction (and even the special registers!) would be the way to go.

It's just a shame that there is no "official" library for people that needs to code for older CPUs. That would be another interesting Fasm project should post this in Projects an idea section.

1 more suggestion for your example Tomasz, since hckr83 certainly wants some error messages to be displayed if anything else than 8086 is written:
Code:
;example that disallows BSWAP, stop the assembling and display the  error message
bswap   equ _bswap

bswap   eax
    

I got 1 more feature request: Coder should be able to throw own compile time errors that would make Fasm stop with a defined error code, so you could write own error "handlers" like this:
Code:
macro   bswap   A{
  display "8086 illegal instruction: bswap"
  error -1;Fasm should simply stop here
}

bswap   eax
    

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 10 Feb 2007, 21:26
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
Quote:

je equ short je
jb equ short jb


Shouldn't that be je equ je short?? Razz

Anyways, yes, I was thinking about this but too afraid to really say anything. Then again, all I wanted was "use16" to default to non-386 jumps (no "0F .. .. .." encodings!). I figured this could be done (in order of difficultly) via equ, macro ("if op1 in <>" to selectively make some jumps short by default), using an external tool like sed, or adjusting FASM's src.
Post 11 Feb 2007, 02:26
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
Finally I have written an include file that disallows anything else than plain 8086, but thought it's quiet carefully written, it's not complete yet, but you can suretainly guess in what direction this goes when it's finished:
Code:
_inc_8086:
;check if we are 16bits (use16)
virtual
  mov   ax,bx
  load  .prefix0 from $$
end virtual
if .prefix0 = 66h
  display "ERROR: 8086-program not compiled with use16!"
end if
;note: 64bit registers, memory and addressing are completely
;forbidden in 16bit mode so we don't have to care about that from now on!

;define error messages
.illegal_addr_size      equ     "Illegal address size"
.illegal_operand_size   equ     "Illegal operand size"
.illegal_regs           equ     "Illegal registers"
.constants_not_allowed  equ     "Constants are not allowed"
.shift_cnt_not_1        equ     "Shift count not 1"

;this push-macro is rather complete, it only lack of 2 things:
;*pushing multiple values must be separated with commas instead of spaces
;    (could maybe be solved with "match", no idea how to do)
;*errors are reported in this macro, so you will have a little overhead if you
;    accidentially used a non-8086 feature. I guess there is no work around
;    for this little problem with current fasm, since there is no way to make
;    custom error messages that stops fasm from assembling your program
macro   push    [A]{
local   .instr
  .instr:
  ;32bit operands implicitly disallowed
  push  A
  load  .prefix0 from .instr
  .prefix1= 0
  if (.prefix0 = 67h) | (.prefix0 = 66h)
    load        .prefix1 from .instr+1
  end if
  ;disallow constants
  if A eqtype 0
    display     .constants_not_allowed
    push
  ;disallow 32bit addresses
  else if (.prefix0 = 67h) | (.prefix1 = 67h)
    display     .illegal_addr_size
    push
  ;disallow 32bit operands
  else if (.prefix0 = 66h) | (.prefix1 = 66h)
    display     .illegal_operand_size
    push
  ;disallow control registers, how comes that Fasm got cr5-cr9?
  ;I didn't knew they even existed, are they documented somewhere?
  else if (A in <cr0,cr1,cr2,cr3,cr4,cr5,cr6,cr7,cr8,cr9>)
    display     .illegal_regs
    push
  end if
}
pushw   fix     push
pushd   fix     .illegal_instr

;this is the shl macro that basically disallows immediate values !=1
;all other shift instruction macros are analogous
macro   shl     A,B{
local   .instr
  .instr:
  shl   A,B
  load  .prefix0 from .instr
  load  .prefix1 from .instr+1
  ;disallow shifts != 1
  if (B eqtype 0) & (B <> 1)
    display     .shift_cnt_not_1
    shl
  ;disallow 32bit addresses
  else if (.prefix0 = 67h) | (.prefix1 = 67h)
    display     .illegal_addr_size
    shl
  ;disallow 32bit operands
  else if (.prefix0 = 66h) | (.prefix1 = 66h)
    display     .illegal_operand_size
    shl
  end if
}
;...    TODO: other instruction macros

;disallowing entire instructions like this
movzx   equ     .illegal_instr
;...    your task to complete

;prefixes must also be reimplemented as macros or else multiple prefixes would
;undergo the 8086-conformity checking and stuff like
;lock   pop     eax
;would re-allowing it!
macro   lock    [A]{
  common
        lock
        A
}
macro   repz    [A]{
  common
        repz
        A
}
macro   repnz   [A]{
  common
        repnz
        A
}
rep     fix     repz
repe    fix     repz
repne   fix     repnz
    

Also usage is quiet simple, see this example program
Code:
use16

;only8086.inc is the name of the above include file
include "%SomeFunnyLibPath/only8086.inc"

        push    ax,dx,cs;this should work
        shl     dx,1;this too
        shl     word [ax],1;this too
        push    10;not allowed
        shl     ax,7;this neither
        shl     ax,7;this neither
        push    eax;this neither
    

If I got some time in the next days/weeks, I will complete it

I'm thankful for any suggestions

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 12 Feb 2007, 00:11
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
Okay, here's my attempt at preventing 386+ jumps (0F .. .. ..). If a short jump is out of range, I do a simple workaround. (If you want to see what FASM would normally do, then change all je after Komenco: to jz (or do a quick sed -i '/Komenco/,$s/\<je\>/jz/' JMP16.ASM ... assuming GNU sed 4.x).

N.B. I have not written/understood a lot of macros very well, so this may be completely wrong. But anyways, here's my two cents ...

Code:
; ----------------------------------------------------------------------
;
; JMP16.ASM -- avoiding 386+ near jumps (0Fh .. .. ..), if unnecessary
;
; Tuesday, February 13, 2007   7:56pm
;
; rugxulo AT bellsouth SPAM_SUX (dot) net
; tested w/ FASMD 1.67.18    Smile
;
; ***   N.B. Only 'je' is done, for now (I hope it's correct !!)   ***
;
; ----------------------------------------------------------------------
;
; ( complete list of all kinds of jumps, from TABLES.INC):
;
;   ja,jb,jc,je,jg,jl,jo,jp,js,jz,jae,jbe,jge,jle,jmp,jna,jnb,jnc,
;   jne,jng,jnl,jno,jnp,jns,jnz,jpe,jpo,jcxz,jnae,jnbe,jnge,jnle
;
; ( we're ignoring jecxz,jrcxz )
;
; ----------------------------------------------------------------------


macro goto cond,me {
@@:
  if ((me < @b) & (@b-me > 126)) | ((me > @b) & (me-@b > 129))
    jn#cond @f
    jmp me
  else
    j#cond me
  end if
@@:
}

macro je a*,b {
      if a eqtype short
        short fix
        goto e,b
      else
        goto e,a
      end if
}

org 100h

Komenco:
        times 127 nop                    ; short jump here = max. 126
        je Komenco                       ; should be 2-byte short jump
Okay:   times 128 nop
        je Fino
        times 128 nop                    ; short jump here = max. 127
Fino:
        ret

; EOF
    


EDIT: The only way to really know if your code outputs unsupported opcodes is to disassemble the binary after assembling.

BIEW color-codes instructions according to cpu set (but only interactively). Of course, since the 8086 only supports 6-byte opcodes max., you could always use diStorm64 (updated today!) and do a grep for '(0[7-9])\|([^0][0-9])', but that is somewhat unreliable. (At least NDISASM reports 386+ jumps as "near", so you can search for that.)
Post 14 Feb 2007, 03:16
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
if anyone is interested in an 8086only include file, I'm currently writing one, but this will suretainly take a while again


Last edited by MCD on 16 Feb 2007, 06:46; edited 1 time in total
Post 14 Feb 2007, 16:24
View user's profile Send private message Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
*drums* here it is, a full featured include file for fasm, that will bark if anything else than 8086 instructions were used.

simply use it like this:
Code:
use16 
 
include "%SomeFunnyLibPath/only8086.inc" 
 
        push    ax,dx,cs;this should work 
        shl     dx,1;this too 
        shl     word [ax],1;this too 
        push    10;not allowed 
        shl     ax,7;this neither 
        shl     ax,7;this neither 
        push    eax;this neither 
    

I'm thankful for any suggestions.

the only thing I didn't figured out was how to make push/pop macros that accept space separated operands when pushing/poping multiple ones. Instead you must write something like:
Code:
push    ax,bx,cx    

when pushing multiple operands. Does anyone know how to fix this?

EDIT: attachment removed, there is a newer version in a later post

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||


Last edited by MCD on 17 Feb 2007, 04:15; edited 1 time in total
Post 16 Feb 2007, 06:46
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
Quote:
when pushing multiple operands. Does anyone know how to fix this?
Have you tried with IRPS under a "common" block of the macro?

Thanks for posting your work Smile
Post 16 Feb 2007, 13:39
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
MCD, my example above is generating 386+ jumps (four bytes: 0Fh .. .. ..) even when including your ONLY8086.INC file.

"je My_label" should have "short" in the middle if you want to stop and report an error. Otherwise, you'll have to do some kind of workaround like I did above.
Post 16 Feb 2007, 20:54
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904
Tomasz wrote:

Quote:
While with 8086/286/386 it was quite simple and straightforward, with more modern instructions sets that are often just turned on or off by a feature bits etc. it would be a more trouble than it is worth (in my opinion).


OK, the "modern" stuff like MMXxxx/SSEyyy would cause trouble Confused

But a method of limiting to official instructions of 8086, 80286, 80386 and
80486 would be useful. Smile

_________________
Bug Nr.: 12345

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

Status: Closed: NOT a Bug
Post 17 Feb 2007, 01:35
View user's profile Send private message Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
rugxulo wrote:
MCD, my example above is generating 386+ jumps (four bytes: 0Fh .. .. ..) even when including your ONLY8086.INC file.

"je My_label" should have "short" in the middle if you want to stop and report an error. Otherwise, you'll have to do some kind of workaround like I did above.

Thanks for the hint, I had completely forgetten this in the 2day-rush I coded that. (I never thought I could do such a think so fast)

There is another important thing I had forgotten: I haven't checked instructions for bad fs/gs segment registers, which aren't allowed on 8086 neither.

But here is a revised version of my "only8086.inc" which fixes all that:
(except that you still have to write "push ax,bx,cx" with commas Sad )


Description: fixed: disallow rel jumps that are not short
fixed: disallow fs/gs segment registers
fixed: some small (structural) improvements

Download
Filename: only8086.inc
Filesize: 21.31 KB
Downloaded: 521 Time(s)


_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 17 Feb 2007, 04:13
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
MCD, I tried downloading it but at 300bps, my 8086 isn't quite done yet (I might have to wait a few years). Anyways, kudos! Laughing
Post 18 Feb 2007, 05:58
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
rugxulo wrote:
MCD, I tried downloading it but at 300bps, my 8086 isn't quite done yet (I might have to wait a few years). Anyways, kudos! Laughing

OMG... your modem is even older than my v90 ROFL Very Happy Shocked

but even with 300bps, it should be downloaded ~ 10-15 minutes, so where is the problem?

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 18 Feb 2007, 07:31
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
MCD wrote:

but even with 300bps, it should be downloaded ~ 10-15 minutes, so where is the problem?


Bah, your math skills have slayed my joke! (*cough* *cough* ... ack) Wink

It'd be even faster to download if you .ZIP'd it. Razz

P.S. Actually, my old 486 (from 1994) had a 2400 bps modem, initially. (And nowadays we think 56k is slow!)

EDIT: Yes, well, I forgot that most websites have ads, heavy graphics, and sometimes even video, flash, or other multimedia to bloat up everything (ugh). (Yes, I know, you can disable most of that, but still, kinda rampant misuse of embedded media ... hint hint, MySpace.)
Post 18 Feb 2007, 20:00
View user's profile Send private message Visit poster's website Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 604
Location: Germany
rugxulo wrote:
MCD wrote:

but even with 300bps, it should be downloaded ~ 10-15 minutes, so where is the problem?


Bah, your math skills have slayed my joke! (*cough* *cough* ... ack) Wink

maybe I falsely assumed that you meant 300 bits/second with 300bps, but I gues you meant 300 baud/second Wink

BTW: how do you manage to download the Fasm archive with THAT high connection speed (even the smalles, Linux version is about 178kByte)?

rugxulo wrote:

It'd be even faster to download if you .ZIP'd it. Razz

well, I could make a special small version where the most often used symbols are abbreviated since they take up much space. would you also take bz2-files? since this compression is even better for text files.

rugxulo wrote:

P.S. Actually, my old 486 (from 1994) had a 2400 bps modem, initially.

Actually, I still have a combined RS232/RS485 external modem with 1200 baud/s laying somewhere around here, but I can't figure out where I left that?

_________________
MCD - the inevitable return of the Mad Computer Doggy

-||__/
.|+-~
.|| ||
Post 19 Feb 2007, 22:28
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
MCD wrote:

BTW: how do you manage to download the Fasm archive with THAT high connection speed (even the smalles, Linux version is about 178kByte)?


FASM.EXE is the first file in the DOS distro, <sarcasm> so I just tell my 300 bps modem to stop downloading after 50k or so, and I can manually fix the truncated .ZIP file to allow extraction. </sarcasm> Laughing

The best download method would be PPM compression (e.g. UHarc), but if someone doesn't have that, I guess I'd just suggest something simpler (sfx for .LZH or .ESP is about 3k).
Post 20 Feb 2007, 05:25
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2335
Location: Usono (aka, USA)
Trixter from Oldskool.org recently gave me a few comments about this ONLY8086.INC file:

Quote:

I've got a few comments from poking around the source:

;currently, the "aam imm" and "aad imm" versions are disabled cause they
;probably didn't exist on 8086

Actually, they exist on all Intel procs, even 808x. However, a common upgrade for clones was the NEC V20 (8088) or V30 (8086) and it did **NOT** emulate the bug, so such aad/aam immed. will fail on such a proc. So it's a good idea to not use them.

;note: "pop cs" already allowed by fasm

Since POP CS is *only* valid on 808x there is really no reason to use it for anything.

macro loopw A{ chk_instr loopw,A }
macro loopzw A{ chk_instr loopzw,A }
macro loopew A{ chk_instr loopew,A }
macro loopnzw A{ chk_instr loopnzw,A }
macro loopnew A{ chk_instr loopnew,A }

Even though these signify the use of 16-bit cx, you might want to double-check that the actual opcode form is no different from the regular form.

You also have a lot of floating-point stuff disabled in the macro -- 808x had 8087, it's not all invalid Smile but obviously you can't have floating-point in an 808x .COM because it won't run on machines without the co-processor.
Post 12 Mar 2008, 04:06
View user's profile Send private message Visit poster's website 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-2019, Tomasz Grysztar.

Powered by rwasa.