# Module AsmSupport

**URL:** <https://clarionhub.com/t/module-asmsupport/516>\
**Category:** docs\
**Tags:** asm\
**Created:** [January 20, 2016, 10:48pm UTC](https://clarionhub.com/t/module-asmsupport/516 "2016-01-20T22:48:22Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![brahn](https://clarionhub.com/user_avatar/clarionhub.com/brahn/32/756_2.png) [@brahn](https://clarionhub.com/u/brahn)\
**Post date:** [January 20, 2016, 10:48pm UTC](https://clarionhub.com/t/module-asmsupport/516/1 "2016-01-20T22:48:22Z")

</div>

Here is another one from Carl that I found on the newsgroups:

> Carl W. Sumner [his-email@compuserve.com](mailto:his-email@compuserve.com)  
> Re: Assembler in Clarion

The c compiler syntax is very standard. Any book on C will do. No header files though.  
The assembler is harder but to get the op codes I just opened the assembler exe in the bin subdir in a hex editor and they jumped out at me.

Here are the notes I have built and collected over the years.

**Note:**  
These directives are equivalents of a `#ifdef _WIN32 / #endif`. The reason for the data segment was actually the result of a copy and paste from some other larger body of code.

```auto
module AsmSupport

%T - ifdef - true
%F - ifndef - false
%E - endif
 
(* Segment Attributes *)
 
use16 = 00H
use32 = 01H
 
abs_align = 00H
byte_align = 20H
word_align = 40H
para_align = 60H
page_align = 80H
dword_align = 0A0H
 
dont_combine = 00H
memory_combine = 04H
public_combine = 08H
stack_combine = 14H
common_combine = 18H
 
(* %T _WIN32 *)
 
segment _DATA(DATA, use32 + dword_align + public_combine)
segment _TEXT(CODE, use32 + dword_align + public_combine)
 
select _TEXT
 
section
 
public _DynPolygon :
 
extrn Cla$POLYGON
 
  call Cla$POLYGON
  ret 0
 
(* %E *)
 
end

```

* * *

```auto
module Call
 
(* Segment Attributes *)
 
use16 = 00H
use32 = 01H
 
abs_align = 00H
byte_align = 20H
word_align = 40H
para_align = 60H
page_align = 80H
dword_align = 0A0H
 
dont_combine = 00H
memory_combine = 04H
public_combine = 08H
stack_combine = 14H
common_combine = 18H
 
(* %T _WIN32 *)
 
segment _DATA(DATA, use32 + dword_align + public_combine)
segment _TEXT(CODE, use32 + dword_align + public_combine)
 
select _TEXT
 
section
 
public _DebugBreak :
 
  db 204
  ret 0
 
(* %E *)
 
end

```

### (1) Changes/incompatibilities

Some memory operands need to be given an explicit type where none was  
needed previously, e.g.

```auto
    push word [bp][-6]
    pop word [bp][-6]

```

Some floating point instructions need to have the specifier moved to just in front of the memory operand, e.g.

```auto
    fld st(0), qword [si]

```

rather than

```auto
    fld qword st(0), [si]

```

There are many new opcodes. All opcodes are now reserved and cannot be used as labels e.g.

```auto
    loop = 2 (loop instruction)
    str = -6 (store task register instruction)
    ....

```

### (3) New Features

Out of range jumps are automatically corrected, using 386 jump opcodes or extra jumps where necessary.

All 8086/8087 … 386/387/486 opcodes are supported. The correct segment override, data and address prefixes are automatically generated.

The size of operands is specified using byte/word/dword/fword/qword/tbyte/ptr/near/far.

fword means 48-bits, made up of a 16-bit segment + 32-bit offset.

ptr means a 16-bit segment + 16-bit offset.

dword means a 32-bit offset.

near means a word or dword depending on whether the current segment  
is 16 or 32 bit.

far means ptr or fword depending on whether the current segment  
is 16 or 32 bit.

e.g.

```auto
    call near xxx
    call near [edi]
    and dword [di], 1
    fstp st(0), qword [esp]
    call ptr far_proc_in_16_bit_seg
    call fword far_proc_in_32_bit_seg

```

32-bit segments are specified by the least significant bit of the segment attribute. Equates suitable for specifying segment attributes are as follows:

```auto
    (* segment attributes *)
    use16 = 0H
    use32 = 1H
 
    abs_align = 00H
    byte_align = 20H
    word_align = 40H
    para_align = 60H
    page_align = 80H
    dword_align = 0A0H
 
    dont_combine = 00H
    memory_combine = 04H
    public_combine = 08H
    stack_combine = 14H
    common_combine = 18H

```

A typical usage is then

```auto
    segment _TEXT('CODE',use16+byte_align+public_combine)

```

Equated symbols may now be given any expression which can be used as an operand for an instruction, rather than just a numeric constant.  
For example:

```auto
    v6 = word [bp][-6]
    ...
    mov ax, v6

```

Simple (parameter-less) macros can be defined.  
For example:

```auto
    macro movsb "movs byte [si], byte es:[di]"

```

Note that no processing is performed during macro definition except to look for the delimiter. In particular there is no conditional processing or macro expansion. The delimiter may any non-blank character and may be repeated. The delimiter(s) are removed when the macro is invoked.

A symbol can be purged (deleted) from the symbol table using purge fred

### (4) The reserved words are as follows:

```auto
      byte
      word
      dword
      fword
      qword
      tbyte
      db
      dw
      dd
      df
      log2
      power2
      ptr
      seg
      vdisp
      far
      near
      end
      extrn
      group
      include
      macro
      module
      org
      public
      purge
      section
      segment
      select
      st

```

The register names are:

```auto
    es cs ss ds fs gs
    ax cx dx bx sp bp si di
    eax ecx edx ebx esp ebp esi edi
    al cl dl bl ah ch dh bh
    cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7
    dr0 dr1 dr2 dr3 dr4 dr5 dr6 dr7
    tr0 tr1 tr2 tr3 tr4 tr5 tr6 tr7
    st(0) st(1) st(2) st(3) st(4) st(5) st(6) st(7)

```

The opcode names (also reserved) are:

```auto
    aaa aad aam aas adc add and arpl
    bound bsf bsr bswap bt btc btr bts
    call clc cld cli clts cmc cmp cmps
    cmpxchg daa das dec div enter esc halt
    idiv imul in inc ins int into invd
    invlpg jmp
    jb jae je jne jbe ja jp jpo
    jl jge jle jg jo jno js jns
    lahf lar lds lea leave les lfs lgdt
    lgs lidt lldt lmsw lods
    lsl lss ltr mov movs movsx movzx mul
    neg nop not or out outs pop push
    rcl rcr rol ror sahf sar sbb scas
    retf retn
    setb setae sete setne setbe seta setp setpo
    setl setge setle setg seto setno sets setns
    sgdt shl shld shr shrd
    sidt sldt smsw stc std sti stos str
    sub test verr verw wbinvd fwait xadd xchg
    xlats xor
 
    f2xm1 fabs fadd faddp fbld fbstp fchs fclex
    fcom fcomp fcompp fdecstpfdiv fdivp fdivr fdivrp
    ffree fiadd ficom ficomp fidiv fidivr fild fimul
    fincstp finit fist fistp fisub fisubr fld fld1
    fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz
    fmul fmulp fnop fpatan fprem fptan frndint frstor
    fsave fscale fsetpm fsqrt fst fstcw fstenv fstp
    fstsw fsub fsubp fsubr fsubrp ftst fxam fxch
    fxtract fyl2x fyl2xp1 fsin fcos fsincos fprem1 fucom
    fucomp fucompp fdisi feni
 
    lock rep repne
 
    cbw cwd iret pusha pushf popa popf
    jcxz loop loope loopne
 
    cwde cdq iretd pushad pushfd popad popfd
    jecxz loopd looped loopned
 
    ret

```

### (5) Things to watch out for:

The meaning of an instruction is derived from the opcode or operands, and prefixes are generated as necessary e.g.

```auto
    cwde
    cdq
    iretd
    jecxz lab
    loopd lab
    pushad
    pushfd
    popad
    popfd
 
    push dword 0
    push dword [si]

```

Note that loop/loope/loopne always means “loop on cx”. To loop on `ecx` `loopd/looped/loopned` must be used. (This is not the same as Microsoft where the meaning of loop depends on the whether the current segment is 32-bit)

However the the default size of the offset of a label depends on whether the current segment is 16-bit or 32-bit.

```auto
  extrn fred
  inc byte es:[fred]

```

The offset size can be specified explicitly, e.g.

```auto
  extrn fred
  inc byte es:[dword fred] (* 32-bit offset *)
  inc byte es:[word fred] (* 16-bit offset *)

```

### (6) The assembler requires string instructions to have operands.

The old short forms may be expressed as macros:

```auto
macro lodsb "lods byte [si]"
macro lodsw "lods word [si]"
macro stosb "stos byte es:[di]"
macro stosw "stos word es:[di]"
macro scasb "scas byte es:[di]"
macro scasw "scas word es:[di]"
macro movsb "movs byte [si], byte es:[di]"
macro movsw "movs word [si], word es:[di]"
macro cmpsb "cmps byte [si], byte es:[di]"
macro cmpsw "cmps word [si], word es:[di]"
macro xlat "xlats byte [bx]"

```

However for readability I suggest using the long forms.  
32-bit addressing is achieved by using esi/edi.  
The source segment may be over-ridden, e.g.  
e.g. `lodsb byte ss:[si] )`  
Beware of doing this in conjunction with rep on 8086’s since on an interrupt multiple prefixes are not saved.

Other opcodes which are defined as macros are as follows:

```auto
macro repe "rep"
macro repz "rep"
macro repnz "repne"
 
macro jc "jb"
macro jnc "jnb"
macro jnae "jb"
macro jnb "jae"
macro jz "je"
macro jnz "jne"
macro jna "jbe"
macro jnbe "ja"
macro jpe "jp"
macro jnp "jpo"
macro jnge "jl"
macro jnl "jge"
macro jng "jle"
macro jnle "jg"
 
macro setnae "setb"
macro setnb "setae"
macro setz "sete"
macro setnz "setne"
macro setna "setbe"
macro setnbe "seta"
macro setpe "setp"
macro setnp "setpo"
macro setnge "setl"
macro setnl "setge"
macro setng "setle"
macro setnle "setg"

```
