Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add High Level Assembly language #5194

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/linguist/languages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,16 @@ Haxe:
- ".hxsl"
tm_scope: source.hx
language_id: 158
High Level Assembly:
type: programming
group: Assembly
aliases:
- hla
extensions:
- ".hla"
tm_scope: source.assembly
ace_mode: assembly_x86
language_id: 101725121
HiveQL:
type: programming
extensions:
Expand Down
303 changes: 303 additions & 0 deletions samples/High Level Assembly/str_cpyz.hla
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
// https://github.com/mcandre/hla/blob/cea2b64754194e5dfb19e1961c1d1048d5221a52/windows-stdlib/strings/str_cpyz.hla
// I, Randall Hyde, hereby agree to waive all claim of copyright (economic
// and moral) in all content contributed by me, the user, and immediately
// place any and all contributions by me into the public domain; I grant
// anyone the right to use my work for any purpose, without any
// conditions, to be changed or destroyed in any manner whatsoever
// without any attribution or notice to the creator. I also absolve myself
// of any responsibility for the use of this code, the user assumes all
// responsibilities for using this software in an appropriate manner.
//
// Notice of declaration of public domain, 7/12/2006, by Randall Hyde



unit stringUnit;
?@nodisplay := true;
?@nostackalign := true;

#include( "strings.hhf" )
#include( "excepts.hhf" )

/********************************************************************/
/* */
/* cpyz- */
/* */
/* zsrc is a zero-terminated string. This function converts it to */
/* an HLA string and stores it into dest. */
/* */
/********************************************************************/


procedure str.cpyz( zstr:zstring; dest:string );
@noframe;

begin cpyz;

push( ebp );
mov( esp, ebp );
push( eax );
push( ecx );
push( edi );
push( esi );
pushfd();

cld();

// First, compute the length of the zero-terminated string
// so we can determine if we need to raise an exception.
//
// Start the length computation by aligning ourselves on
// a dword boundary:

mov( zstr, ecx );
test( ecx, ecx ); // Make sure it's a non-NULL pointer
jz AttemptToDerefNULL;

mov( ecx, eax );
and( %11, eax );
jz dwordAligned;

cmp( (type byte [ecx]), 0 );
jz GotLen;
add( 1, ecx );
cmp( eax, %11 );
je dwordAligned;

cmp( (type byte [ecx]), 0 );
jz GotLen;
add( 1, ecx );
cmp( eax, %10 );
je dwordAligned;

cmp( (type byte [ecx]), 0 );
jz GotLen;
add( 1, ecx );


dwordAligned:
sub( 32, ecx ); // To counteract add immediately below.
ZeroLoop:
add( 32, ecx ); // Skip chars this loop just processed.
ZeroLoop2:
mov( [ecx], eax ); // Get next four chars into EAX.
and( $7f7f7f7f, eax ); // Clear H.O. bit (note:$80->$00!)
sub( $01010101, eax ); // $00 and $80->$FF, all others have pos val.
and( $80808080, eax ); // Test all H.O. bits. If any are set, then
jnz MightBeZero0; // we've got a $00 or $80 byte.

mov( [ecx+4], eax ); // The following are all in-line expansions
and( $7f7f7f7f, eax ); // of the above (we'll process 32 bytes on
sub( $01010101, eax ); // each iteration of this loop).
and( $80808080, eax );
jnz MightBeZero4;

mov( [ecx+8], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jnz MightBeZero8;

mov( [ecx+12], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jnz MightBeZero12;

mov( [ecx+16], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jnz MightBeZero16;

mov( [ecx+20], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jnz MightBeZero20;

mov( [ecx+24], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jnz MightBeZero24;

mov( [ecx+28], eax );
and( $7f7f7f7f, eax );
sub( $01010101, eax );
and( $80808080, eax );
jz ZeroLoop;

// The following code handles the case where we found a $80
// or a $00 byte. We need to determine whether it was a zero
// byte and the exact position of the zero byte. If it was a
// $80 byte, then we've got to continue processing characters
// in the string.


// Okay, we've found a $00 or $80 byte in positions
// 28..31. Check for the location of the zero byte, if any.

add( 28, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 4..7:

MightBeZero4:
add( 4, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 8..11:

MightBeZero8:
add( 8, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 12..15:

MightBeZero12:
add( 12, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 16..19:

MightBeZero16:
add( 16, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 20..23:

MightBeZero20:
add( 20, ecx );
jmp MightBeZero0;

// If we get to this point, we've found a zero byte in
// positions 24..27:

MightBeZero24:
add( 24, ecx );

// If we get to this point, we've found a zero byte in
// positions 0..3 or we've branched here from one of the
// above conditions

MightBeZero0:
mov( [ecx], eax ); // Get the original four bytes.
cmp( al, 0 ); // See if the first byte contained zero.
je GotLen;
inc( ecx );
cmp( ah, 0 ); // See if the second byte contained zero.
je GotLen;
inc( ecx );
test( $FF_0000, eax ); // See if byte #2 contained a zero.
je GotLen;
inc( ecx );
test( $FF00_0000, eax ); // See if the H.O. byte contained zero.
je GotLen;

// Well, it must have been a $80 byte we encountered.
// (Fortunately, they are rare in ASCII strings, so all this
// extra computation rarely occurs). Jump back into the zero
// loop and continue processing.

inc( ecx ); // Skip bytes we just processed.
jmp ZeroLoop2; // Don't bother adding 32 in the ZeroLoop!

// Compute the length of the string as the difference between
// the address of the zero byte and the start of the string.

GotLen:
sub( zstr, ecx );
mov( zstr, esi );
mov( dest, edi );

// Make sure our destination string pointer is non-null.

test( edi, edi );
jz AttemptToDerefNULL;

// Make sure that the source string will fit in the destination string.

cmp( ecx, (type str.strRec [edi]).maxlen );
ja StringOverflow;


// Save as the length of the destination string.

mov( ecx, (type str.strRec [edi]).length );

// Must have special cases for a length that is a multiple of two or four
// bytes:

add( 1, ecx ); // Move zero terminating byte, too.
mov( ecx, eax );
and( %11, eax );
jz movsDword;
cmp( eax, %10 );
jz movsWord;
cmp( eax, %11 );
je move3;

// The remainder of the length divided by four is 3.
// So we have to move a single byte and then we can
// use a dword move to handle everything else.

movsb();
sub( 1, ecx );
jz allDone;
shr( 2, ecx );
rep.movsd();
jmp allDone;

move3:
// The length to move is not divisible by two or four,
// and the remainder of the division by four is 1.
// so move three bytes here.

movsb();
sub( 1, ecx );
jz allDone;

// Fall through to move the next two bytes.


movsWord:

// Compute the number of dwords to copy (rather than bytes).
// Then copy the data.

movsw();
sub( 2, ecx );
jz allDone;

movsDword:

// Compute the number of dwords to copy (rather than bytes).
// Then copy the data.

shr( 2, ecx );
rep.movsd();

allDone:
popfd();
pop( esi );
pop( edi );
pop( ecx );
pop( eax );
pop( ebp );
ret( _parms_ );

AttemptToDerefNULL:
raise( ex.AttemptToDerefNULL );

StringOverflow:
raise( ex.StringOverflow );

end cpyz;

end stringUnit;
1 change: 1 addition & 0 deletions vendor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting
- **Harbour:** [hernad/atom-language-harbour](https://github.com/hernad/atom-language-harbour)
- **Haskell:** [atom-haskell/language-haskell](https://github.com/atom-haskell/language-haskell)
- **Haxe:** [vshaxe/haxe-TmLanguage](https://github.com/vshaxe/haxe-TmLanguage)
- **High Level Assembly:** [Nessphoro/sublimeassembly](https://github.com/Nessphoro/sublimeassembly)
- **HiveQL:** [adidonato/language-hql](https://github.com/adidonato/language-hql)
- **HolyC:** [codingdandy/holyc.tmbundle](https://github.com/codingdandy/holyc.tmbundle)
- **Hy:** [Slowki/hy.tmLanguage](https://github.com/Slowki/hy.tmLanguage)
Expand Down