#1  
Old 27th May 2013, 10:42 PM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Lightbulb Portable Assembly Language

I just felt like blogging an idea I came up with, to write Intel assembly language code with syntax bi-compliant with both the GNU assembler (`gas` module) and the Microsoft Macro Assembler (`ML.EXE`) (and TASM I guess, maybe others).

Usually an assembly language is not very portable between even the assemblers supporting it (never minding operating system issues) unless its standardization, lexical and otherwise, was high enough.

Well I tested this assembly source file with both the Microsoft MASM and the GNU assemblers.
Two entirely, fiercely different-syntax assemblers!
Consider this example code to find the factorial of any 16-bit integer `cx`, set to 5 internally:

Code:
;.intel_mnemonic
;.intel_syntax noprefix /*
.386; /*
.model flat, C
;*/

.data
;# nothing to store in this section

;/*
.code
;*/.text # GNU assembler calls the section `.text`

;.global _main /*
_main PROC;*/
init:
    MOV     eax, 1;
    MOV     ecx, 5; # factorial !(x) of x = 5
    TEST    cx, cx;
    JZ      done; # !0 = 1
multiply:
    IMUL    ax, cx;
    DEC     cx;
    TEST    cx, cx;
    JNZ     multiply;
    NOP;
done:
    RET;/*
_main ENDP
;*//*
END
;*/
(Stole this color highlighting off Notepad++, which primarily supports MASM assembly syntax.)

I tested it; it assembles and works perfectly under the syntax interpretations of both GAS and MASM (and TASM I guess, didn't test).
It could probably third in support for FASM somewhere...doesn't seem possible with NASM, but GAS is the most multi-OS anyway.

I came up with this solution based on the following rules tying in the coincidences of GNU, Microsoft assemblers:
  • MASM (and almost any Intel assembler) uses the semicolon `;` to start a comment, but GAS uses `;` as an explicit end-of-line marker, without pressing Enter/Return to actually make a new line. As such, use `;` to comment out things you want only GAS to see, but not MASM.
  • GAS has 3 acceptable ways of commenting x86 assembly: the two C/C++-style comments (/*comment*/ and //comment), and the standard shell-style comment more assembly languages for other architectures use: # comment. You can use /* comment */ in GNU asm (prefixed of course by a ; so MASM ignores it) to make GAS ignore stuff you want only MASM to see.
  • Use of `.intel_mnemonic` and `.intel_syntax noprefix`. This is the most crucial part about the portability between GAS and most other Intel x86 assemblers. AT&T syntax was annoying the crap out of lots of people, so starting from some version of the GNU binutils, GAS began to support those directives for the Intel assembly syntax, plus the removal of `%`-prefixed register codes.
  • Avoidance of hexadecimals, octals, and binaries. I'm not sure, but I think there is no way to write these in ways that both MASM and GAS will accept. Microsoft MASM expresses hexadecimals as ??h, while GAS uses 0x??. The idea is the same for other arithmetic bases, so just use decimals.
Reply With Quote
  #2  
Old 27th May 2013, 11:04 PM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Default

Duh, forgot to add this.

It works btw.
With the cx hard-wired to 5:

ans = 1;
ans *= 2 * 3 * 4 * 5;
... and 1*2*3*4*5 = 120, which the Windows console spits out:

Code:
factorial.exe
ECHO %errorlevel%
output: 120

Identical C code:
Code:
int main(void)
    {
    register int Ans = 1;
    register int x = 5;

    if (x == 0)
        return (Ans);
    do
        {
        Ans *= x;
        --x;
        } while (x != 0);
    return (Ans);
    }
Reply With Quote
  #3  
Old 28th May 2013, 12:53 AM
mudlord_ mudlord_ is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Dec 2012
Posts: 383
Default

Another nice thing is Xbyak

http://homepage1.nifty.com/herumi/soft/xbyak_e.html
Reply With Quote
  #4  
Old 28th May 2013, 01:51 AM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Default

Haha. Well it seems effective at fast-finding machine output of small algorithms. I usually just pass /S to GCC to see the assembly output, but then again I think that the code itself can always be a little more portable when hand-written by man than by a compiler/JIT sort of thing.

NASM is supposed to be pretty portable, too, though. Interesting that Xbyak used that in their examples.

Though the way I see it, C is the most portable assembly language. :P

Last edited by HatCat; 28th May 2013 at 01:54 AM.
Reply With Quote
  #5  
Old 28th May 2013, 07:21 PM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Default

Miraculous. It works in the a86 DOS assembler, too.

I just had to make a couple fundamental changes since a86 was only free/didn't require $50 pay and registration if you programmed for MS-DOS:
Code:
;/*
.code
;*/.text # GNU assembler calls the section `.text`

;.global _main /*
_main PROC;*/
init:
    MOV     ax, 1;
    MOV     cx, 5; # factorial !(x) of x = 5
    TEST    cx, cx;
    JE      done; # !0 = 1
multiply:
    MUL     al;
    DEC     cx;
    TEST    cx, cx;
    JNZ     multiply;
    NOP;
done:
    RET;/*
_main ENDP
;*//*
END
;*/
It still works in GNU asm and MASM simultaneously!
I don't know how, but I guess A86's minimization of keywords/directives/assembly language non-code tokens is still compliant enough to adhere to Microsoft Macro Assembler.

I might never get it working in NASM, though, but that is a little too rebellious against the standard Intel syntax anyway. Working in 3 assemblers at once is good enough for me (edit: 4, I keep forgetting TASM).

Last edited by HatCat; 28th May 2013 at 07:27 PM.
Reply With Quote
  #6  
Old 3rd June 2013, 03:39 AM
mudlord_ mudlord_ is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Dec 2012
Posts: 383
Default

Quote:
Haha. Well it seems effective at fast-finding machine output of small algorithms.
Not just that. I find it useful for spewing random segments of ASM which is then fed into a data array to be copied as raw machine code chunks. I use that in my executable packer as a form of obfuscation (the bytestream from the JIT assembler is written directly to a host executable, from the EXE packer). That, and wrapping nonsense code with antidebug measures is super nice too.

I daresay these sort of assemblers (Xbyak, AsmJit), have other uses too besides small code segments. Desmume uses AsmJit in its dynamic recompiler to emit large amounts of code.
Reply With Quote
  #7  
Old 3rd June 2013, 04:26 PM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Default


Built this 64-byte executable command in A86 MS-DOS assembler, a simple animated rainbow scroller demo using the BIOS VGA mode 19 palette pixel plotter.
It builds under GNU assembler, too, but crashes because GAS doesn't support 16-bit code. (Using 32-bit registers is not enough; the parent interrupt function 16d is DOS-specific.)

DOSBox's fault are those premature line-blitting video interrupts.
If I fixate CPU cycles per second to something less than like 500 I could take proper screenshots.

Quote:
Originally Posted by haxatax View Post
Not just that. I find it useful for spewing random segments of ASM which is then fed into a data array to be copied as raw machine code chunks. I use that in my executable packer as a form of obfuscation (the bytestream from the JIT assembler is written directly to a host executable, from the EXE packer). That, and wrapping nonsense code with antidebug measures is super nice too.

I daresay these sort of assemblers (Xbyak, AsmJit), have other uses too besides small code segments. Desmume uses AsmJit in its dynamic recompiler to emit large amounts of code.
Mmm...sounds like cool features I guess, but I think programming with an assembler and conveniently disassembling code is its most important feature.

I don't understand JIT stuff very much, along with obfuscation, wrapping nonsense code, or why I would want to spew random segments of ASM, but I guess I just lack the experience to read what you meant properly.
Reply With Quote
  #8  
Old 4th June 2013, 01:09 AM
mudlord_ mudlord_ is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Dec 2012
Posts: 383
Default

Ha awesome, you are doing my sort of coding now, thats excellent!

Now if you do a full 3D tunnel in 128 bytes, people would be amazed.

Quote:
I don't understand JIT stuff very much, along with obfuscation, wrapping nonsense code, or why I would want to spew random segments of ASM, but I guess I just lack the experience to read what you meant properly.
Context was coding my own DRM/EXE packer. Think of UPX, but on steroids to slow down reverse engineering. So far I have junkcode emitting/code obfuscation/randomized code segments to fool antiviruses, but I want more like scrambled import tables, and possibly even a disassembling code filter to improve compression ratios. (RAR also uses a disassembler to improve code compression of x86/x64 EXEs).
Reply With Quote
  #9  
Old 4th June 2013, 04:31 AM
HatCat's Avatar
HatCat HatCat is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Feb 2007
Location: In my hat.
Posts: 16,256
Default

Hmm, a tunnelvision rainbow screensaver.

Should be possible.
Well from school I know that circles are graphed on a coordinate plane using:
Code:
(x*x) + (y*y) == (r*r) //r:  radius
So by incrementing the radius, x, and y, one would need some sort of FP approximation (not sure yet if floating-point math can be done in DOS before the x87) to render close-enough circles on the screen. In a 128-byte executable? ...well, why not, most of why my linear rainbow scroller is 64 bytes was me partially unrolling the massive pixel blitting loop, otherwise I could have made that as small as 32 B

Quote:
Originally Posted by haxatax View Post
Context was coding my own DRM/EXE packer. Think of UPX, but on steroids to slow down reverse engineering. So far I have junkcode emitting/code obfuscation/randomized code segments to fool antiviruses, but I want more like scrambled import tables, and possibly even a disassembling code filter to improve compression ratios. (RAR also uses a disassembler to improve code compression of x86/x64 EXEs).
Oh yeah, that's right.

You used to argue with zilmar about the whole beta protection and executable packing services, thing. Forgot.

I'm not usually into executable packing because then I add complexity in exchange for the illusion of a smaller program. I prefer plainly releasing the binary in the form I made it and the form it's made to expand into RAM as uncompressed, but that's only my disposition on it.

Did want to disassemble one or two of Jabo's plugins to look at some of the OS interface/timing solutions, just never bothered to look up how to crack the hacked UPX compression.
Reply With Quote
  #10  
Old 4th June 2013, 10:30 AM
mudlord_ mudlord_ is offline
Alpha Tester
Project Supporter
Senior Member
 
Join Date: Dec 2012
Posts: 383
Default

http://pouet.net/prod.php?which=61389

Thats what I meant by full 3D. With completely dynamic paths, etc
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT. The time now is 07:44 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.