Author Topic: Linux and LIBC  (Read 1329 times)

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Linux and LIBC
« on: June 19, 2017, 02:25:10 AM »
I've added _LINUX and _WIN64 to switch -elf, -elf64, and -win64

-elf --> _LINUX = 1
-elf64 --> _LINUX = 2 + _WIN64 = 1
-win64 --> _WIN64 = 1

libc.inc use SYSCALL if elf is defined.
Code: [Select]
ifdef _LINUX
_CType equ <syscall>
_CDecl equ <syscall>
__cdecl equ <syscall>

This enables use of the include files for LIBC functions.

Test case used for 64-bit:
Code: [Select]
include stdio.inc

    .code

main proc argc:SINT, argv:ptr

    .for r12d=argc, r13=argv, ebx=0: r12d: r12d--, ebx++, r13+=size_t
       
    printf("[%d]: %s\n", ebx, [r13])
    .endf
    xor eax,eax
    ret
main endp

    end

Output:
Code: [Select]
nidud@nidud-VB ~/asmc $ ./asmc -q -Iinclude -elf64 arg64.asm
nidud@nidud-VB ~/asmc $ gcc -o arg64 arg64.o
nidud@nidud-VB ~/asmc $ ./arg64 1 2 3
[0]: ./arg64
[1]: 1
[2]: 2
[3]: 3

Test case used for 32-bit:
Code: [Select]
include stdio.inc

    .code

main proc argc:SINT, argv:ptr

    .for ebx=argc, esi=argv, edi=0: ebx: ebx--, edi++, esi+=size_t

    printf("[%d]: %s\n", edi, [esi])
    .endf
    xor eax,eax
    ret
main endp

    end

Output:
Code: [Select]
nidud@nidud-VB ~ $ cd asmc
nidud@nidud-VB ~/asmc $ ./asmc -elf -Iinclude arg32.asm
Asmc Macro Assembler Version 2.24
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: arg32.asm
nidud@nidud-VB ~/asmc $ gcc arg32.o -o arg32
nidud@nidud-VB ~/asmc $ ./arg32
[0]: ./arg32
nidud@nidud-VB ~/asmc $ ./arg32 1 2 3
[0]: ./arg32
[1]: 1
[2]: 2
[3]: 3

I also changed the default size of indirect addressing using register in 64-bit. This was 4 but now 8. This effect :VARARG arguments using -elf64 and -win64.
Code: [Select]
    printf("[%d]: %s\n", ebx, [r13])

Greenhorn

  • Member
  • **
  • Posts: 98
Re: Linux and LIBC
« Reply #1 on: April 04, 2018, 06:01:24 AM »
Hi nidud,

I'm trying to get ASMC working for me, but it throws an error "A2005: symbol redefinition : _WIN64".
After removing the switch /D"_WIN64" from command line and quoted out the one and only conditional definition of _WIN64 in my header files, I still get that error. Now I'm at a loss about that and don't know what to do to get it working.

In my opinion the definition of such macros shoul be the responsibility of the toolset where it is needed. In this case the windows header files or it should be the programmer's responsibility.

However, keep on the good work on ASMC.

Kind Regards
Greenhorn

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: Linux and LIBC
« Reply #2 on: April 04, 2018, 06:38:08 AM »
I ended up writing quite a few of these command lines:
asmc -q -win64 -D_WIN64 -ws -D_UNICODE $*.asm

So the logic here is:
-win64 defines _WIN64
-ws defines _UNICODE
-elf defines _LINUX=1
-elf64 defines _LINUX=2

However, the first version created a problem if the symbol was already defined. This is fixed in later versions so the Linux version needs an update. The development is currently done in assembler so the C source to build an updated version is currently missing.

EDIT:
Added version 2.27J-Linux to the download page.
« Last Edit: April 04, 2018, 10:14:27 AM by nidud »

Greenhorn

  • Member
  • **
  • Posts: 98
Re: Linux and LIBC
« Reply #3 on: April 05, 2018, 04:29:24 AM »
Hi,

thanks for your quick reply.

The problem occurs with using Windows. I've got ASMC working with Visual Studio 2010.

Command line is:
Code: [Select]
asmc.exe /c -win64 -Zp8 /nologo /ws /Sg /Zi /Fo"x64\Debug\%(FileName).obj" /D"WIN32" /D"_DEBUG" /D"_WINDOWS" /D"_UNICODE" /D"UNICODE" /Fl"x64\Debug\%(Filename).lst" /I"D:\Win7Inc\include" /Cp /W2 /win64 /Zp8
The only possible definition of _WIN64 is in Winasm.inc (originally from Japhet's WinInc files).
So I've quoted out:
Code: [Select]
ifndef _WIN64
if near eq 0ff08h   ;64-bit enabled?
;_WIN64 equ <>
endif
endif

Downloaded version 2.27J from today and unfortunately the error still occurs.
Seems that I'm too stupid. Cannot find the error. Searched all files for _WIN64 ... *sigh*


Regards

Greenhorn

  • Member
  • **
  • Posts: 98
Re: Linux and LIBC
« Reply #4 on: April 05, 2018, 04:38:30 AM »
Sorry, and yes, I'm definitely too stupid !

The command line contains: -win64 and -Zp8, which is doubled defined in command line. But it's not generated by Visual Studio. VS uses "/" and not "-" as switch prefix. So this is also generated by ASMC ?

Now I'm a little bit confused, but at first I'll go and rubbing the tomatoes out of my eyes ...

Edit:
Mmmh, "-win64 -Zp8" appears in project settings command line, so ... mmh.   :icon_confused:

Edit:
Aaargh, got it. I've modified Japhet's VS2010 Cunstom Build Rule files to create the ASMC build files. Japhet predefind in *.props file -win64 -Zp8 for x64 build.

Sorry for stealing your time, nidud.

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: Linux and LIBC
« Reply #5 on: April 05, 2018, 06:18:36 AM »
You posted under Linux and LIBC so I assumed Linux.

Not sure what to add here other than whats already said except to give a few examples on how it works. All the samples below works:

asmc -win64 test.asm
asmc -win64 -D_WIN64 test.asm
asmc -win64 -D"_WIN64" test.asm
Code: [Select]
    .code
ifdef _WIN64
    mov al,1
endif
    end

Same with this code:
Code: [Select]
_WIN64 equ <>

    .code
ifdef _WIN64
    mov al,1
endif
    end

This however ends with a fatal error:
asmc /c -win64 -Zp8 /nologo /ws /Sg /Zi /D"WIN32" /D"_DEBUG" /D"_WINDOWS" /D"_UNICODE" /D"UNICODE" /Fl /Cp /W2 /win64 /Zp8 test.asm

ASMC : fatal error A1901: Internal Assembler Error


The reason is the second (or first) definition of -win64. Bit tricky that switch so there can be only on of them.

Quote
The only possible definition of _WIN64 is in Winasm.inc (originally from Japhet's WinInc files).
Doesn't really matter but _WIN64 should not be defined inside any of the windows include files but the IF NEAR thing is clever thought. Asmc also comes with a full set of Windows include files.

Quote
The command line contains: -win64 and -Zp8, which is doubled defined in command line. But it's not generated by Visual Studio. VS uses "/" and not "-" as switch prefix. So this is also generated by ASMC ?
Not sure I understand the question. Asmc do not interact with Visual Studio so if you have any problems with VS you should direct your questions to Microsoft.

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: Linux and LIBC
« Reply #6 on: April 05, 2018, 06:58:07 AM »
Sorry for stealing your time, nidud.

Well, the Linux version got a face-lift so I guess some good came out of it.

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: Linux and LIBC
« Reply #7 on: August 28, 2018, 06:35:58 AM »
Added VARARG support for SYSCALL 64-bit. The option WIN64:AUTO<stack> and ALIGN<16> is also added.

The stack frame created is 208 byte for six 64-bit and eight 128-bit registers. The frame:
Code: [Select]
00000000                        xsprintf proc buffer:LPSTR, format:LPSTR, argptr:VARARG
00000000  55                *   push rbp
00000001  488BEC            *   mov rbp, rsp
00000004  4881ECD0000000    *   sub rsp, 0 + @ReservedStack
0000000B  C744240810000000  *    mov DWORD PTR [rsp+8], 16
00000013  C744240C30000000  *    mov DWORD PTR [rsp+12], 48
0000001B  4889542430        *    mov [rsp+48], rdx
00000020  48894C2438        *    mov [rsp+56], rcx
00000025  4C89442440        *    mov [rsp+64], r8
0000002A  4C894C2448        *    mov [rsp+72], r9
0000002F                    *   .if al
0000002F  84C0              *   test al, al
00000031  7437              *   jz  @C0001
00000033  0F29442450        *    movaps [rsp+80], xmm0
00000038  0F294C2460        *    movaps [rsp+96], xmm1
0000003D  0F29542470        *    movaps [rsp+112], xmm2
00000042  0F299C2480000000  *    movaps [rsp+128], xmm3
0000004A  0F29A42490000000  *    movaps [rsp+144], xmm4
00000052  0F29AC24A0000000  *    movaps [rsp+160], xmm5
0000005A  0F29B424B0000000  *    movaps [rsp+176], xmm6
00000062  0F29BC24C0000000  *    movaps [rsp+192], xmm7
0000006A                    *   .endif
0000006A                    *   @C0001:
0000006A  488D8424E0000000  *    lea rax, [rsp+224]
00000072  4889442410        *    mov [rsp+16], rax
00000077  488D442420        *    lea rax, [rsp+32]
0000007C  4889442418        *    mov [rsp+24], rax
00000081  488D442408        *    lea rax, [rsp+8]

The frame is 16 byte aligned and start at offset 8. The first DWORD indicate the start of the first 64-bit argument which start at offset 32. The second DWORD is the size of 64-bits arguments. Offset 16 holds the address of the first 16-byte aligned offset beyond the frame and offset 24 the start address of the first 64-bit argument (32). The va_start() address is loaded in RAX.

The caller sets AL if any xmm registers is used. This is done by the assembler. The total number of arguments is currently limited to six. In the sample below the include file sets WIN64:3, otherwise option win64:auto should be set to ensure alignment.

Code: [Select]
include stdio.inc

    .code

xsprintf proc buffer:LPSTR, format:LPSTR, argptr:VARARG

    vsprintf(buffer, format, rax)
    ret

xsprintf endp

main proc

  local string[256]:sbyte
  local r0:real8, r1:real8

    xsprintf( &string, "const %d.%d\n", 1, 2 )
    printf( &string )

    mov rax,3.0
    mov rdx,2.0
    mov r0,rax
    mov r1,rdx

    movsd xmm2,r0
    divsd xmm2,r1

    xsprintf( &string, "%f / %f = %f\n", r0, r1, xmm2 )
    printf( &string )
    ret

main endp

    end

main:
Code: [Select]
        push    rbp
        mov     rbp, rsp
        sub     rsp, 272
        mov     ecx, 2
        mov     edx, 1
        lea     rsi, [DS0000]
        lea     rdi, [rbp-100H]
        xor     eax, eax       
        call    xsprintf       
        lea     rdi, [rbp-100H]
        xor     eax, eax       
        call    printf         
        mov     rax, 4008000000000000H
        mov     rdx, 4000000000000000H
        mov     qword ptr [rbp-108H], rax
        mov     qword ptr [rbp-110H], rdx
        movsd   xmm2, qword ptr [rbp-108H]
        divsd   xmm2, qword ptr [rbp-110H]
        movq    xmm1, qword ptr [rbp-110H]
        movq    xmm0, qword ptr [rbp-108H]
        lea     rsi, [DS0001]
        lea     rdi, [rbp-100H]
        mov     eax, 1         
        call    xsprintf       
        lea     rdi, [rbp-100H]
        xor     eax, eax       
        call    printf
        leave         
        ret           

A new Linux version (2.28) with samples and include files is uploaded to the download page.