News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

More high level directives in UASM and DOS

Started by nikkho, June 06, 2017, 06:50:36 PM

Previous topic - Next topic

nikkho

I am a former TASM user, than then moved to JWASM. I mainly develop DOS programs, and this is why I miss default DOS binaries, that were available under JWASM. Do you consider releaseing them too?

Also, since the time of TASM, I miss some high level/SMART directives that were available, for instance:
- FASTIMUL dest_reg, source_r/m, value
This instruction is much like the trinary IMUL operation available on the 80186, 80286, and 80386 processors. The dest_reg destination register is a WORD register (or it can be DWORD on the 80386). source_r/m is a register or memory address that must match the size of the destination. value is a fixed, signed constant multiplicand. FASTIMUL uses a combination of IMUL, MOV, NEG, SHL, ADD, and SUB instructions to perform its function. This function destroys the source register or memory address, and leaves the processor flags in an indeterminate state.

- SHL/SHR/RCL/RCR/ROL/ROR: When .8086 was used, it was unrolled such as SHR AX, 2, as SHR AX, 1 / SHR AX, 1.

- SETFLAG - a "smart-flag" instruction implementing OR

- TESTFLAG - a "smart-flag" instruction implementing TEST

- FLIPFLAG - a "smart-flag" instruction implementing XOR

- CLRFLAG - [bytepointer.com edit] I think this is a doc bug where the writers meant to specify MASKFLAG as CLRFLAG does not exist and likely never existed; there is no CLRFLAG identifier embedded within this version or any version of TASM; CLRFLAG is also not documented anywhere else but the one place it was ever mentioned: the keywords table for version 3.0.

- MASKFLAG (u) - a "smart-flag" instruction implementing AND; accidentally documented in the new keywords for version 3.0 table as CLRFLAG

- SETFIELD generates code that sets a value in a record field. Its syntax follows:

- GETFIELD retrieves data from a record field. It functions as the logical reverse of the SETFIELD instruction. Its syntax follows:               


As a bonus, I would like to see some kind of optional optimizations options, that if enabled will for instance replace, and give a warning message when done, about some inneficient casuistics:
- mov ah, 3 / mov al, 5 => mov ax, 0305h
- dec cx / cmp cx, 0 / je label => dec cx / je label
- shl cx, 1 / shl cx, 1 => shl cx, 2 (if .186 or later)
- cmp cx, 0 / je label => jcxz label
- mov eax, 0 => xor eax, eax (if flags are not used)
- cmp eax, 0 => test eax, eax (if flags are not used)
- mov eax, -1 => or eax, -1 (if flags are not used)

Those would allow to get an extra performance boost while assembling with UASM from an automatic ASM generated listing, and why not, to automatically optimize some third party codes.

Reason to be it optional by using a command-line option and a directive, is of course that it could broke some internal code that could rely on timmings or code sizes.

Looking forward to hear from you.

jj2007

Quote from: nikkho on June 06, 2017, 06:50:36 PM
- SETFIELD generates code that sets a value in a record field. Its syntax follows:

- GETFIELD retrieves data from a record field. It functions as the logical reverse of the SETFIELD instruction. Its syntax follows:               
????

Where is the syntax? I might be willing to adapt SetField and GetField to DOS - how much are you willing to pay?

nikkho

Thank you for your reply jj2007
Information about those extended directives, can be obtained from TASM manual. I will copy them here:

The SETFIELD instruction

SETFIELD generates code that sets a value in a record field. Its syntax follows:

SETFIELD field_name destination_r/m , source_reg field_name is the name of a record member field, destination _r/m for SETFIELD is a register or memory address of type BYTE or  WORD (or DWORD for the 80386). source_reg must be a register of the same size or smaller. If the source is smaller than the destination, the source register must be the least significant part of another register that is the same size as the destination. This full size register is called the operating register. Use this register to shift the value in the source register so that it's aligned with the destination. For example.

F00 RECORD R0:1,R1 :4,R2 : 3 , R3 : 1

SETFIELD Rl AX,BL
SETFIELD Rl AX,BH

; operating register is BX
; illegal!

SETFIELD shifts the source register efficiently to align it with the the entire contents of the operating register are destroyed by the SETFIELD field in the destination, and ORs the result into the destination operation, register. Otherwise, SETFIELD modifies only the operating register and the processor flags.
To perform its function, SETFIELD generates an efficient but extended series of the following instructions: XOR, XCHG, ROL, ROR, OR, and MOVZX.

If you're using SETFIELD when your source and target registers are the same, the instruction does not OR the source value to itself. Instead, SETFIELD ensures that the fields of the target register not being set will be zero.

SETFIELD does not attempt to clear the target field before ORing the new value. If this is necessary, you must explicitly clear the field using the MASKFLAG instruction.

GETFIELD retrieves data from a record field. It functions as the logical reverse of the SETFIELD instruction. Its syntax follows:
GETFIELD field_name destination_reg , source_r/m

fieldjiame and destination _t -eg function as they do for SETFIELD. You can use source_r/m as you would for sourcejreg (for SETFIELD). For example,

F00 RECORD R0:l,Rl:4,R2:3,R3:l

GETFIELD Rl BL,AX /operating register is BX GETFIELD Rl BH,AX /illegal!

"^ Note that GETFIELD destroys the entire contents of the operating register.

GETFIELD retrieves the value of a field found in the source register or memory address, and sets the pertinent portion of the destination register to that value. This instruction affects no other registers than the operating register and the processor flags.

To accomplish its function, GETFIELD generates an efficient but extended series of the following instructions: MOV, XCHG, ROL, and ROR.

If you're using the GETFIELD instruction when your source and target registers are the same, the instruction will not generate the nonfunctional MOV target , source instruction.

Additional fast immediate multiply instruction Turbo Assembler provides a special immediate multiply operation for efficient array indexing. FASTIMUL addresses a typical problem that occurs when you create an array of structures. There is no immediate multiply operation available for the 8086 processor. Even for the more advanced processors, multiplication using shifts and adds is significantly faster in some circumstances than using the standard immediate IMUL instruction. Based on the currently specified processor, Turbo Assembler's FASTIMUL instruction chooses between the most efficient sequence of shifts and adds available, and the current processor's immediate IMUL operation (if any). FASTIMUL has the following syntax:

FASTIMUL dest_reg, source_r/m, value

This instruction is much like the trinary IMUL operation available on the 80186, 80286, and 80386 processors. The destjreg destination register is a WORD register (or it can be DWORD on the 80386). source_r/m is a register or memory address that must match the size of the destination, value is a fixed, signed constant multiplicand.
FASTIMUL uses a combination of IMUL, MOV, NEG, SHL, ADD, and SUB instructions to perform its function. This function destroys the source register or memory address, and leaves the processor flags in an indeterminate state.

johnsa

I personally don't have plans to compile a DOS version, but the code and make files are all in the github repository. If someone wants to compile and test a DOS version I'd be happy to host in on the site.

I would think that several of those functions could be implemented as macros, which would be a cleaner solution than modifying the assembler itself. As for the automatic optimisation it would be quite a big job for very little reward, given the trivial nature of some of the optimisations, one would expect someone writing asm code to pick that up on their own. What I had been debating however was an automatic static analysis function which given a specified architecture would provide instruction timings, latency and potential stall / dependency chain indicators in the listing.

These days that is where the optimisation counts far more so than the classic bitwise/single instruction substitutions like  in the 386/486 days. I suspect that in a lot of cases the micro-code and decode units already do some of this on their own in secret via macro-op fusion and so on..

jj2007

Quote from: johnsa on June 07, 2017, 06:58:15 AM
I personally don't have plans to compile a DOS version, but the code and make files are all in the github repository. If someone wants to compile and test a DOS version I'd be happy to host in on the site.

Great :t Maybe nikkho volunteers to take that project in his hands? I can't, because 16-bit code won't run on my machine :(

habran

Hi nikkho :biggrin:

Welcome to the board.

Maybe you are not aware that on this board there is another assembler called ASMC which is Nidud's babe.
AFAIK Nidud is still maintaining DOS version, so you can ask him if he is interested to look in to your request.
Cod-Father

nikkho

It is not being that easy. Even if I am able to build 2.13 with no problems with OpenWatcom for Win32 and Win64, DOS versions do not build properly.