The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: KradMoonRa on May 12, 2018, 05:46:13 AM

Title: Fighting the Error: .ENDPROLOG found before EH directives
Post by: KradMoonRa on May 12, 2018, 05:46:13 AM
Hi,  :biggrin:

Sharing some off my fights with the uams error messages ":(ERROR: endprolog found before off EH directives)", "first gess" no idea what that means!, Searching manual and examples, HOW MAN really so simple uasm option for part of code saving, (thank you #jhonsa), I'm really loving the way uams it's so simple and workload clear.

The fight are, the unwind xdata code for .allocstack .endprolog .setframe .pushreg, don't like the RSP stack option and frame auto, but I like the RSP option, this produce clear and clean stack proc's, no extra sub or add rsp stack in with.

the simple trick of adding the options to save before and pop after the proc's with prolog frames, fix everything.
Quote
option frame:noauto
option stackbase:rbp
code.............
option frame:auto
option stackbase:rsp

Part of sourceware org libffi asm code for WIN64. Successfully compiles with uasm and VC15 x64. I'm trying to add it to llvm and clang build's and later with clang compile uasm for linux and finish llvm-gcc cross compiler in windows for linux and uasm, and port the code easely (I think....).


;/* If these change, update src/mips/ffitarget.h. */
FFI_TYPE_VOID equ 0   
FFI_TYPE_INT equ 1
FFI_TYPE_FLOAT equ 2   
FFI_TYPE_DOUBLE equ 3
;if 0
;FFI_TYPE_LONGDOUBLE equ 4
;else
FFI_TYPE_LONGDOUBLE equ FFI_TYPE_DOUBLE
;endif
FFI_TYPE_UINT8      equ 5   
FFI_TYPE_SINT8      equ 6
FFI_TYPE_UINT16     equ 7
FFI_TYPE_SINT16     equ 8
FFI_TYPE_UINT32     equ 9
FFI_TYPE_SINT32     equ 10
FFI_TYPE_UINT64     equ 11
FFI_TYPE_SINT64     equ 12
FFI_TYPE_STRUCT     equ 13
FFI_TYPE_POINTER    equ 14
FFI_TYPE_COMPLEX    equ 15

;/* This should always refer to the last type code (for sanity checks) */
FFI_TYPE_LAST       equ FFI_TYPE_COMPLEX

FFI_CLOSURES equ 1
FFI_GO_CLOSURES equ 1

FFI_TYPE_SMALL_STRUCT_1B equ (FFI_TYPE_LAST + 1)
FFI_TYPE_SMALL_STRUCT_2B equ (FFI_TYPE_LAST + 2)
FFI_TYPE_SMALL_STRUCT_4B equ (FFI_TYPE_LAST + 3)
FFI_TYPE_MS_STRUCT       equ (FFI_TYPE_LAST + 4)

ifdef __X64__
FFI_TRAMPOLINE_SIZE equ 24
FFI_NATIVE_RAW_API equ 0
else
FFI_TRAMPOLINE_SIZE equ 12
FFI_NATIVE_RAW_API equ 1  ;/* x86 has native raw api support */
endif

;/* Constants for ffi_call_win64 */
STACK equ 0
PREP_ARGS_FN equ 32
ECIF equ 40
CIF_BYTES equ 48
CIF_FLAGS equ 56
RVALUE equ 64
FN equ 72

include win64_uasm_macros.inc

option casemap:none
ifndef __X64__
.686P
.model flat
option stackbase:esp ; RSP or RBP are supported options for the stackbase.
else
.X64P
option stackbase:rsp ; RSP or RBP are supported options for the stackbase.
endif
option win64:15 ; 11/15 for RSP and 1-7 for RBP.
option frame:auto

ifndef LIBFFI_ASM
define LIBFFI_ASM

include win64_uasm.inc

;#define LIBFFI_ASM
;#include <fficonfig.h>
;#include <ffi.h>

;/* Constants for ffi_call_win64 */
;#define STACK 0
;#define PREP_ARGS_FN 32
;#define ECIF 40
;#define CIF_byteS 48
;#define CIF_FLAGS 56
;#define RVALUE 64
;#define FN 72

;/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
;    extended_cif *ecif, unsigned bytes, unsigned flags,
;    unsigned *rvalue, void (*fn)());
;*/

.code

_TEXT segment

extrn __chkstk:near
extrn ffi_closure_win64_inner:near

public ffi_closure_win64_UW
public ffi_call_win64_UW

ffi_closure_win64 proto UX_VECCALL (voidarg)
ffi_call_win64 proto UX_VECCALL (voidarg)

ffi_closure_win64_UW proc near 
   ; exception/unwind handler body 

   ret 0 

ffi_closure_win64_UW endp

ffi_call_win64_UW proc near 
   ; exception/unwind handler body 

   ret 0 

ffi_call_win64_UW endp

option frame:noauto
option stackbase:rbp

;;; ffi_closure_win64 will be called with these registers set:
;;;    rax points to 'closure'
;;;    r11 contains a bit mask that specifies which of the
;;;    first four parameters are float or double
;;;
;;; It must move the parameters passed in registers to their stack location,
;;; call ffi_closure_win64_inner for the actual work, then return the result.
;;;
ffi_closure_win64 proc UX_VECCALL (voidarg) frame : ffi_closure_win64_UW
;; copy register arguments onto stack
test r11, 1
jne first_is_float
mov qword ptr [rsp+8], rcx
jmp second
first_is_float:
movlpd qword ptr [rsp+8], xmm0

second:
test r11, 2
jne second_is_float
mov qword ptr [rsp+16], rdx
jmp third
second_is_float:
movlpd qword ptr [rsp+16], xmm1

third:
test r11, 4
jne third_is_float
mov qword ptr [rsp+24], r8
jmp fourth
third_is_float:
movlpd qword ptr [rsp+24], xmm2

fourth:
test r11, 8
jne fourth_is_float
mov qword ptr [rsp+32], r9
jmp done
fourth_is_float:
movlpd qword ptr [rsp+32], xmm3

done:
.allocstack 40
sub rsp, 40
.endprolog
mov rcx, rax ; context is first parameter
mov rdx, rsp ; stack is second parameter
add rdx, 48 ; point to start of arguments
mov rax, ffi_closure_win64_inner
call rax ; call the real closure function
add rsp, 40
movd xmm0, rax ; If the closure returned a float,
; ffi_closure_win64_inner wrote it to rax
ret 0
ffi_closure_win64 endp

ffi_call_win64 proc UX_VECCALL (voidarg) frame : ffi_call_win64_UW
;; copy registers onto stack
mov qword ptr [rsp+32], r9
mov qword ptr [rsp+24], r8
mov qword ptr [rsp+16], rdx
mov qword ptr [rsp+8], rcx
.pushreg rbp
push rbp
.allocstack 48
sub rsp, 48 ; 00000030H
.setframe rbp, 32
lea rbp, qword ptr [rsp+32]
.endprolog

mov eax, dword ptr CIF_BYTES[rbp]
add rax, 15
and rax, -16
call __chkstk
sub rsp, rax
lea rax, qword ptr [rsp+32]
mov qword ptr STACK[rbp], rax

mov rdx, qword ptr ECIF[rbp]
mov rcx, qword ptr STACK[rbp]
call qword ptr PREP_ARGS_FN[rbp]

mov rsp, qword ptr STACK[rbp]

movlpd xmm3, qword ptr [rsp+24]
movd r9, xmm3

movlpd xmm2, qword ptr [rsp+16]
movd r8, xmm2

movlpd xmm1, qword ptr [rsp+8]
movd rdx, xmm1

movlpd xmm0, qword ptr [rsp]
movd rcx, xmm0

call qword ptr FN[rbp]
ret_struct4b$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
jne ret_struct2b$

mov rcx, qword ptr RVALUE[rbp]
mov dword ptr [rcx], eax
jmp ret_void$

ret_struct2b$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
jne ret_struct1b$

mov rcx, qword ptr RVALUE[rbp]
mov word ptr [rcx], ax
jmp ret_void$

ret_struct1b$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
jne ret_uint8$

mov rcx, qword ptr RVALUE[rbp]
mov byte ptr [rcx], al
jmp ret_void$

ret_uint8$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_UINT8
jne ret_sint8$

mov rcx, qword ptr RVALUE[rbp]
movzx   rax, al
mov qword ptr [rcx], rax
jmp ret_void$

ret_sint8$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SINT8
jne ret_uint16$

mov rcx, qword ptr RVALUE[rbp]
movsx   rax, al
mov qword ptr [rcx], rax
jmp ret_void$

ret_uint16$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_UINT16
jne ret_sint16$

mov rcx, qword ptr RVALUE[rbp]
movzx   rax, ax
mov qword ptr [rcx], rax
jmp ret_void$

ret_sint16$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SINT16
jne ret_uint32$

mov rcx, qword ptr RVALUE[rbp]
movsx   rax, ax
mov qword ptr [rcx], rax
jmp ret_void$

ret_uint32$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_UINT32
jne ret_sint32$

mov rcx, qword ptr RVALUE[rbp]
mov     eax, eax
mov qword ptr [rcx], rax
jmp short ret_void$

ret_sint32$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SINT32
jne ret_float$

mov rcx, qword ptr RVALUE[rbp]
cdqe
mov qword ptr [rcx], rax
jmp short ret_void$

ret_float$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_FLOAT
jne short ret_double$

mov rax, qword ptr RVALUE[rbp]
movss dword ptr [rax], xmm0
jmp short ret_void$

ret_double$:
cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
jne short ret_uint64$

mov rax, qword ptr RVALUE[rbp]
movlpd qword ptr [rax], xmm0
jmp short ret_void$

ret_uint64$:
  cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_UINT64
  jne short ret_sint64$

mov rcx, qword ptr RVALUE[rbp]
mov qword ptr [rcx], rax
jmp short ret_void$

ret_sint64$:
  cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_SINT64
  jne short ret_pointer$

mov rcx, qword ptr RVALUE[rbp]
mov qword ptr [rcx], rax
jmp short ret_void$

ret_pointer$:
  cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_POINTER
  jne short ret_int$

mov rcx, qword ptr RVALUE[rbp]
mov qword ptr [rcx], rax
jmp short ret_void$

ret_int$:
  cmp dword ptr CIF_FLAGS[rbp], FFI_TYPE_INT
  jne short ret_void$

mov rcx, qword ptr RVALUE[rbp]
cdqe
mov qword ptr [rcx], rax
jmp short ret_void$

ret_void$:
xor rax, rax

lea rsp, qword ptr [rbp+16]
pop rbp
ret 0
ffi_call_win64 endp

option frame:auto
option stackbase:rsp

_TEXT ends

endif ;LIBFFI_ASM

end
Title: Re: Fighting the Error: .ENDPROLOG found before EH directives
Post by: aw27 on May 12, 2018, 04:36:56 PM
Your approach to exception handling is very wrong.
You should start by reading this article (https://www.codeproject.com/Articles/1212332/bit-Structured-Exception-Handling-SEH-in-ASM).
There is a version for UASM that has been worked out together with Johnsa, I will look for it when I have time.
Title: Re: Fighting the Error: .ENDPROLOG found before EH directives
Post by: Biterider on May 12, 2018, 06:00:44 PM
Hi KradMoonRa
You can take a look here http://masm32.com/board/index.php?topic=6812.msg75472#msg75472 (http://masm32.com/board/index.php?topic=6812.msg75472#msg75472) too.

Biterider
Title: Re: Fighting the Error: .ENDPROLOG found before EH directives
Post by: aw27 on May 12, 2018, 06:59:33 PM
This is the conversion to UASM that has been done based on my mentioned article.

@biterider
lol, you copied almost like the chinese do. But your product does not even support nested catch blocks.