(R)EFLAGS Register - PUSHF/PUSHFD/PUSHFQ - Proc Uses (R)EFLAGS

Started by LiaoMi, January 03, 2020, 03:45:30 AM

Previous topic - Next topic

LiaoMi

Hi,

is it possible to make support for the combination of -Dummy Proc Uses (R)EFLAGS- through the internal compilation algorithm, and for compatibility, report that this feature is used only in UASM  :rolleyes:

HSE

Hi LoaMi !

Have you tried:ifdef __UASM__
   Dummy Proc Uses EFLAGS
else
   Dummy Proc
endif
Equations in Assembly: SmplMath

LiaoMi

Quote from: HSE on January 03, 2020, 08:27:44 AM
Hi LoaMi !

Have you tried:ifdef __UASM__
   Dummy Proc Uses EFLAGS
else
   Dummy Proc
endif


Hi HSE,

I think this option is not supported at all  :undecided:
main.asm(60) : Error A2210: Syntax error: Uses RFLAGS

jj2007

I really wonder why you need an assembler "feature" for such crap. It's a macro assembler, folks...

include \masm32\include\masm32rt.inc ; pure Masm32
include usesFlags.inc

.code

test1 proc arg1, arg2
  usesFlags
  mov eax, arg1
  dec eax ; 123-1=?
  usesFlags
  ret
test1 endp

test2 proc arg1
  usesFlags
  mov eax, arg1
  dec eax ; 123-1=?
  usesFlags
  ret
test2 endp

start:
  xor ebx, ebx ; set the zero flag
  invoke test1, 123, 456
  .if Zero?
print "the usesFlags macro worked fine"
  .else
print "bad luck, it didn't work"
  .endif
  dec ebx ; set the sign flag
  invoke test2, 123
  .if Sign?
MsgBox 0, "the usesFlags macro worked fine", "Hi", MB_OK
  .else
MsgBox 0, "bad luck, it didn't work", "Hi", MB_OK
  .endif
  exit

end start

HSE

Equations in Assembly: SmplMath

johnsa

On a related to note to this, there is a PR change coming into UASM 2.50+ to change the epilogue in 64bits so it doesn't trash the flags. As it stands right now you can't return flags as the stack correction will affect flags.

LiaoMi

Quote from: jj2007 on January 03, 2020, 02:07:44 PM
I really wonder why you need an assembler "feature" for such crap. It's a macro assembler, folks...

include \masm32\include\masm32rt.inc ; pure Masm32
include usesFlags.inc

.code

test1 proc arg1, arg2
  usesFlags
  mov eax, arg1
  dec eax ; 123-1=?
  usesFlags
  ret
test1 endp

test2 proc arg1
  usesFlags
  mov eax, arg1
  dec eax ; 123-1=?
  usesFlags
  ret
test2 endp

start:
  xor ebx, ebx ; set the zero flag
  invoke test1, 123, 456
  .if Zero?
print "the usesFlags macro worked fine"
  .else
print "bad luck, it didn't work"
  .endif
  dec ebx ; set the sign flag
  invoke test2, 123
  .if Sign?
MsgBox 0, "the usesFlags macro worked fine", "Hi", MB_OK
  .else
MsgBox 0, "bad luck, it didn't work", "Hi", MB_OK
  .endif
  exit

end start


Hi jj2007,

QuoteIt's a macro assembler, folks...
:biggrin:  I knew about macros, one fine winter evening wanted aesthetics - Saving Status register when calling a function - https://stackoverflow.com/questions/48146499/saving-status-register-when-calling-a-function - http://www.c-jump.com/CIS77/samples/IO.htm

This code would look simpler  :azn:
itoaproc    PROC   NEAR32
            push   ebp                  ; save base pointer
            mov    ebp, esp             ; establish stack frame
            push   eax                  ; Save registers
            push   ebx                  ;   used by
            push   ecx                  ;   procedure
            push   edx
            push   edi
            pushf                      ; save flags


Thank you!  :thumbsup:



Quote from: johnsa on January 04, 2020, 02:18:51 AM
On a related to note to this, there is a PR change coming into UASM 2.50+ to change the epilogue in 64bits so it doesn't trash the flags. As it stands right now you can't return flags as the stack correction will affect flags.

Hi johnsa,

I did not think about it .. cool  :rolleyes:,we are waiting for a new update  :thumbsup:

jj2007

Quote from: LiaoMi on January 05, 2020, 03:42:48 AMSaving Status register when calling a function - https://stackoverflow.com/questions/48146499/saving-status-register-when-calling-a-function

Most important phrase from that article: Nobody saves it, except in very rare cases

If you have such a rare case, use
pushf   ; explain why
invoke somealgo, 123, 456
popf

aw27

pushf only pushes 2 bytes, not 4 as most people believe. To push 4 bytes we have to use pushfd.
Other than this I am convinced that either using macros or automating the assembler around these little things is an absolute waste of time (and, of course, we can always find ways for such automation/macros break and fail to fulfill its mission) that could be better invested to fix little bugs here and there.  :icon_idea:

jj2007

Right  :thumbsup:

I checked and found only two occurrences of pushfd/popfd in all my sources. It is so rarely used nowadays that implementing a uses flags in the assembler itself is really a waste of time. Besides, the code is more readable with
pushfd
invoke somestuff
popfd

Note, though, that in the old days of DOS, most 21h interrupts returned the carry flag set in case of error. But that is history :cool:

LiaoMi

Quote from: jj2007 on January 05, 2020, 09:03:01 AM
Quote from: LiaoMi on January 05, 2020, 03:42:48 AMSaving Status register when calling a function - https://stackoverflow.com/questions/48146499/saving-status-register-when-calling-a-function

Most important phrase from that article: Nobody saves it, except in very rare cases

If you have such a rare case, use
pushf   ; explain why
invoke somealgo, 123, 456
popf


Hi jj2007,

this is a matter of clarity, you can always write differently, I just suggested a probable opportunity, which, as I understand it, exists in some compilers. I do not pretend for any better implementation. In programs with complex embedded logic, such as interpreters, which can have two or three nested contexts, this is very convenient, but this is only my opinion. This is also convenient for writing drivers. :skrewy:

Execution without USES

.data
;align 8
_COA struct
Val3 WORD 0
Val4 ULONG 0
Val5 WORD 0
Val6 ULONG 0
_COA ends

Val1 USHORT 0
Val2 ULONG 0
Val3 qword 6

_REG struct
reg_rflags     qword 246
reg_rdx         qword 0
reg_rax         qword -50000
_REG ends

COA _COA <?>
REGeflagsEdx _REG <246,0,-50000>

COAsz equ sizeof COA
ValX qword 0ddddddddddddddddh

.code
align 16
mainCRTStartup proc PUBLIC Uses rcx
    mov rbx,COAsz
    mov Val1,1
    mov Val2,2
   
    cmp Val3, 511;
    call Dummy1
    jbe notequal1
    nop
    nop
    nop
    notequal1:
    mov rbx, 256
    cmp Val3, 6
    call Dummy2IdivDword
    jnge equal2
    assume rax:ptr _COA
    lea rax, COA
    mov [rax].Val3, 5
    mov [rax].Val4, 6
    mov [rax].Val5, 7
    mov [rax].Val6, 8
   
    equal2:
   
    ret
mainCRTStartup endp

Dummy1 proc
    ;PUSHFQ
    sub eax, ebx ; = a-b
    sbb edx, edx ; = (b > a) ? 0xFFFFFFFF : 0
    and edx, eax ; = (b > a) ? a-b : 0
    add ebx, edx ; Result is in ebx
    ;popfq
    ret
Dummy1 endp

Dummy2IdivDword proc
;pushfq
push rbx

assume rdi:ptr _REG
    lea rdi, REGeflagsEdx

mov rdx,[rdi].reg_rdx
test edx, 80000000h
jz idiv_dword_edx_pos
;
neg rdx

idiv_dword_edx_pos:
test ebx,80000000h
jz idiv_dword_ebx_pos
;
neg rbx

idiv_dword_ebx_pos:
cmp rdx,rbx
jae DivFault
;
pop rbx
mov ah,byte ptr [rdi].reg_rflags
sahf
mov rax,[rdi].reg_rax
mov rdx,[rdi].reg_rdx
idiv rbx
mov rcx,rax
lahf
mov byte ptr [rdi].reg_rflags,ah
mov [rdi].reg_rax,rcx
mov [rdi].reg_rdx,rdx

    DivFault:
    ;popfq
    ret
Dummy2IdivDword endp

end


Execution with USES

.data
;align 8
_COA struct
Val3 WORD 0
Val4 ULONG 0
Val5 WORD 0
Val6 ULONG 0
_COA ends

Val1 USHORT 0
Val2 ULONG 0
Val3 qword 6

_REG struct
reg_rflags     qword 246
reg_rdx         qword 0
reg_rax         qword -50000
_REG ends

COA _COA <?>
REGeflagsEdx _REG <246,0,-50000>

COAsz equ sizeof COA
ValX qword 0ddddddddddddddddh

.code
align 16
mainCRTStartup proc PUBLIC Uses rcx
    mov rbx,COAsz
    mov Val1,1
    mov Val2,2
   
    cmp Val3, 511;
    call Dummy1
    jbe notequal1
    nop
    nop
    nop
    notequal1:
    mov rbx, 256
    cmp Val3, 6
    call Dummy2IdivDword
    jnge equal2
    assume rax:ptr _COA
    lea rax, COA
    mov [rax].Val3, 5
    mov [rax].Val4, 6
    mov [rax].Val5, 7
    mov [rax].Val6, 8
   
    equal2:
   
    ret
mainCRTStartup endp

Dummy1 proc
    PUSHFQ
    sub eax, ebx ; = a-b
    sbb edx, edx ; = (b > a) ? 0xFFFFFFFF : 0
    and edx, eax ; = (b > a) ? a-b : 0
    add ebx, edx ; Result is in ebx
    popfq
    ret
Dummy1 endp

Dummy2IdivDword proc
pushfq
push rbx

assume rdi:ptr _REG
    lea rdi, REGeflagsEdx

mov rdx,[rdi].reg_rdx
test edx, 80000000h
jz idiv_dword_edx_pos
;
neg rdx

idiv_dword_edx_pos:
test ebx,80000000h
jz idiv_dword_ebx_pos
;
neg rbx

idiv_dword_ebx_pos:
cmp rdx,rbx
jae DivFault
;
pop rbx
mov ah,byte ptr [rdi].reg_rflags
sahf
mov rax,[rdi].reg_rax
mov rdx,[rdi].reg_rdx
idiv rbx
mov rcx,rax
lahf
mov byte ptr [rdi].reg_rflags,ah
mov [rdi].reg_rax,rcx
mov [rdi].reg_rdx,rdx

    DivFault:
    popfq
    ret
Dummy2IdivDword endp

end

jimg

It may be history, but I still use the carry flag to indicate an error in my own routines  :wink2:

daydreamer

Quote from: jj2007 on January 05, 2020, 11:39:17 PM
Right  :thumbsup:

I checked and found only two occurrences of pushfd/popfd in all my sources. It is so rarely used nowadays that implementing a uses flags in the assembler itself is really a waste of time. Besides, the code is more readable with
pushfd
invoke somestuff
popfd

Note, though, that in the old days of DOS, most 21h interrupts returned the carry flag set in case of error. But that is history :cool:
one reason would be code a IF (condition) and (condition) and (condition) and (Condition)....
in a chess engine that goes up and down in a tree ,recursive proc calling itself,so in the end pops all conditions into register and makes use of AND's and final jump on zero flag
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding