flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > may be ability of push_next pop_next left only for register

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 10 Feb 2023, 00:01
push and pop operate expression very weird, everything that could be combined in one argument for push/pop is combined, push 1 1 - will make 2 pushes, push 1 -1 will make 1, push 1 (-1) - will make 2
[X86_64.INC]:
Code:
        ...
      push_mem_store:
        mov     [base_code],0FFh
        mov     [postbyte_register],110b
        call    store_instruction
        jmp     push_done
      push_reg_store:
        call    store_classic_instruction_code
        lods    byte [esi]
        dec     esi
        cmp     al,0Fh
        je      instruction_assembled
        or      al,al
        jz      instruction_assembled
        cmp     byte[operand_size],0
        jnz     invalid_operand
        inc     esi
        cmp     al,10h
        jne     invalid_operand
      push_reg:
        lods    byte [esi]
        mov     ah,al
        sub     ah,10h
        and     ah,al
        test    ah,0F0h
        jnz     push_sreg
        call    convert_register
        test    al,1000b
        jz      push_reg_ok
        or      [rex_prefix],41h
        and     al,111b
        ...       
Code:
        ...
      pop_mem_store:
        mov     [base_code],08Fh
        mov     [postbyte_register],0
        call    store_instruction
        jmp     pop_done
      pop_reg_store:
        call    store_classic_instruction_code
        lods    byte [esi]
        dec     esi
        cmp     al,0Fh
        je      instruction_assembled
        or      al,al
        jz      instruction_assembled
        cmp     byte[operand_size],0
        jnz     invalid_operand
        inc     esi
        cmp     al,10h
        jne     invalid_operand
      pop_reg:
        lods    byte [esi]
        mov     ah,al
        sub     ah,10h
        and     ah,al
        test    ah,0F0h
        jnz     pop_sreg
        call    convert_register
        test    al,1000b
        jz      pop_reg_ok
        or      [rex_prefix],41h
        and     al,111b
        ...    
Code:
        ...
      pop_done:
      push_done: ;could be named push_pop_done and combined together
        lods    byte [esi]
        dec     esi
        cmp     al,0Fh
        je      instruction_assembled
        or      al,al
        jz      instruction_assembled
        jmp     invalid_operand
        ...    

this will make push/pop with sequence of reg allowed, any sequence disallowed if size operator exists or any sequence member other than reg
that behavior is more simple to override & reproduce by macro.

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 10 Feb 2023, 00:01
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20357
Location: In your JS exploiting you and your system
revolution 10 Feb 2023, 13:09
ProMiNick wrote:
push and pop operate expression very weird ...
It isn't weird when you understand it. It is a greedy algorithm. Very simple.
Post 10 Feb 2023, 13:09
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20357
Location: In your JS exploiting you and your system
revolution 10 Feb 2023, 13:11
I find things like push eax 0 edx very useful.

Using macros for everything makes the assembler slow and the sources complicated.
Post 10 Feb 2023, 13:11
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 16 Feb 2023, 00:55
So, since macro extension of every element of push|pop is unreacheble(or extremly expensive to resources). extension should be done at core level, not in macro level.
So, extension itself:
FASMW.ASM
Code:
...
  about:
        invoke  DialogBoxParam,[hinstance],IDD_ABOUT,[hwnd],AboutDialog,0
        cmp     eax, IDYES
        jnz     finish
        invoke  DialogBoxParam,[hinstance],IDD_ADDABOUT,[hwnd],AboutDialog,0
        jmp     finish
  failed:                
...
proc AboutDialog hwnd,msg,wparam,lparam
        push    ebx esi edi
        cmp     [msg],WM_COMMAND
        je      .close
        cmp     [msg],WM_CLOSE
        je      .close
        xor     eax,eax
        jmp     .finish
  .close:
        invoke  EndDialog,[hwnd],[wparam];0
  .processed:
        mov     eax,1
  .finish:
        pop     edi esi ebx
        ret
endp
...
  resource dialogs,\
           IDD_POSITION,LANG_ENGLISH+SUBLANG_DEFAULT,position_dialog,\
           IDD_FIND,LANG_ENGLISH+SUBLANG_DEFAULT,find_dialog,\
           IDD_REPLACE,LANG_ENGLISH+SUBLANG_DEFAULT,replace_dialog,\
           IDD_COMPILE,LANG_ENGLISH+SUBLANG_DEFAULT,compile_dialog,\
           IDD_SUMMARY,LANG_ENGLISH+SUBLANG_DEFAULT,summary_dialog,\
           IDD_ERRORSUMMARY,LANG_ENGLISH+SUBLANG_DEFAULT,error_summary_dialog,\
           IDD_APPEARANCE,LANG_ENGLISH+SUBLANG_DEFAULT,appearance_dialog,\
           IDD_COMPILERSETUP,LANG_ENGLISH+SUBLANG_DEFAULT,compiler_setup_dialog,\
           IDD_CALCULATOR,LANG_ENGLISH+SUBLANG_DEFAULT,calculator_dialog,\
           IDD_ABOUT,LANG_ENGLISH+SUBLANG_DEFAULT,about_dialog,\
           IDD_ADDABOUT,LANG_ENGLISH+SUBLANG_DEFAULT,about_add_dialog  
...
IDD_ADDABOUT      =5309
...
  dialog about_dialog,'About',40,40,172,70,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
    dialogitem 'STATIC',<'flat assembler ',2014h,' version ',VERSION_STRING,0Dh,0Ah,'Copyright ',0A9h,' 1999-2022 Tomasz Grysztar.'>,-1,27,10,144,40,WS_VISIBLE+SS_CENTER
    dialogitem 'STATIC',IDI_MAIN,-1,8,8,32,32,WS_VISIBLE+SS_ICON
    dialogitem 'STATIC','fasm core modified',-1,4,32,164,20,WS_VISIBLE+SS_LEFT
    dialogitem 'BUTTON','About unofficial modification',IDYES,70,28,96,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
    dialogitem 'STATIC','',-1,4,44,164,11,WS_VISIBLE+SS_ETCHEDHORZ
    dialogitem 'STATIC',<'flat editor version ',FEDIT_VERSION_STRING>,-1,4,48,100,20,WS_VISIBLE+SS_LEFT
    dialogitem 'STATIC',<'interface version ',IDE_VERSION_STRING>,-1,4,58,100,20,WS_VISIBLE+SS_LEFT
    dialogitem 'BUTTON','OK',IDOK,124,50,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
  enddialog

  dialog about_add_dialog,'About addition "stack tracing"',40,40,172,70,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
    dialogitem 'STATIC',<'affected fasm core elements:',0Dh,0Ah,' 1. instruction handlers:',9,'         added stack tracing',0Dh,0Ah,' 2. variables:',9,'     added variable stack_distance',0Dh,0Ah,' 3. predefined symbols:',9,9,'       stackorg, %s'>,-1,4,4,167,40,WS_VISIBLE
    dialogitem 'STATIC',<'addition distributed as is',0Dh,0Ah,'addition has no own Copyright',0Dh,0Ah,'addition author - ProMiNick'>,-1,4,44,167,25,WS_VISIBLE
    dialogitem 'BUTTON','OK',IDOK,124,50,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
  enddialog
...    

VARIABLE.INC:
Code:
...
stack_distance dd ?
...    

PARSER.INC:
Code:
...
      get_file_offset_id:
        mov     eax,4
        ret
      get_stacktrace_id:
        mov     eax,6
        ret
      current_address_label_3_characters:
        cmp     word [esi+1],'%%'
        jne     find_label
        add     esi,3
      get_actual_file_offset_id:
        mov     eax,5
        ret
      get_predefined_id:
        cmp     ecx,2
        ja      find_label
        inc     esi
        cmp     cl,1
        je      get_counter_id
        lods    byte [esi]
        mov     ebx,characters
        xlat    [ebx]
        cmp     al,'t'
        je      get_timestamp_id
        cmp     al,'s'
        je      get_stacktrace_id
        sub     esi,2
      find_label:                     
...    

EXPRCALC.INC:
Code:
...
      org_origin_label:
        mov     eax,[addressing_space]
        mov     eax,[eax+18h]
        jmp     make_current_offset_label
      stacktrace_label:
        mov     eax,[stack_distance]
        jmp     make_dword_label_value
      counter_label:
        mov     eax,[counter]
      make_dword_label_value:
        stos    dword [edi]
        xor     eax,eax
        stos    dword [edi]
        add     edi,0Ch
        jmp     calculation_loop
      timestamp_label:
        call    make_timestamp
      make_qword_label_value:
        stos    dword [edi]
        mov     eax,edx
        stos    dword [edi]
        add     edi,0Ch
        jmp     calculation_loop
      predefined_label:
        or      eax,eax
        jz      current_offset_label
        cmp     eax,1
        je      counter_label
        cmp     eax,2
        je      timestamp_label
        cmp     eax,3
        je      org_origin_label
        cmp     eax,4
        je      current_file_offset_label
        cmp     eax,5
        je      actual_file_offset_label
        cmp     eax,6
        je      stacktrace_label
        mov     edx,invalid_value
        jmp     error_undefined
      label_out_of_scope:            
...    

ASSEMBLE.INC:
Code:
...      org_value_ok:
        mov     edx,[symbol_identifier]
        mov     [ebx+14h],edx
        cmp     [output_format],1
        ja      instruction_assembled
        cmp     edi,[code_start]
        jne     instruction_assembled
        cmp     eax,100h
        jne     instruction_assembled
        bts     [format_flags],0
        jmp     instruction_assembled

stackorg_directive:
        lods    byte [esi]
        cmp     al,'('
        jne     stackorg_empty
        cmp     byte [esi],'.'
        je      invalid_value
        call    get_dword_value
        mov     [stack_distance],eax
        jmp     instruction_assembled
      stackorg_empty:
        dec     esi
        and     [stack_distance],0
        jmp     instruction_assembled

label_directive: 
...    

TABLES.INC:
Code:
...
 db 'popa',61h
 dw popa_instruction-instruction_handler 
...
 db 'popf',9Dh
 dw popf_instruction-instruction_handler     
...
 db 'popad',61h
 dw popad_instruction-instruction_handler
 db 'popaw',61h
 dw popaw_instruction-instruction_handler
 db 'popfd',9Dh
 dw popfd_instruction-instruction_handler
 db 'popfq',9Dh
 dw popfq_instruction-instruction_handler
 db 'popfw',9Dh
 dw popfw_instruction-instruction_handler      
...
 db 'pusha',60h
 dw pusha_instruction-instruction_handler      
...
 db 'pushf',9Ch
 dw pushf_instruction-instruction_handler  
...
 db 'pushad',60h
 dw pushad_instruction-instruction_handler
 db 'pushaw',60h
 dw pushaw_instruction-instruction_handler
 db 'pushfd',9Ch
 dw pushfd_instruction-instruction_handler
 db 'pushfq',9Ch
 dw pushfq_instruction-instruction_handler
 db 'pushfw',9Ch
 dw pushfw_instruction-instruction_handler       
...
 db 'stackorg',0
 dw stackorg_directive-instruction_handler  
...
    

X86_64.INC:
Code:
...
pusha_instruction:
        movzx   eax,[code_type]
        add     [stack_distance],eax
        jmp     simple_instruction_except64
pushaw_instruction:
        add     [stack_distance],16
        jmp     simple_instruction_16bit_except64
pushad_instruction:
        add     [stack_distance],32
        jmp     simple_instruction_32bit_except64
popa_instruction:
        movzx   eax,[code_type]
        sub     [stack_distance],eax
        jmp     simple_instruction_except64
popaw_instruction:
        sub     [stack_distance],16
        jmp     simple_instruction_16bit_except64
popad_instruction:
        sub     [stack_distance],32
        jmp     simple_instruction_32bit_except64

pushf_instruction:
        movzx   eax,[code_type]
        shr     eax,3
        add     [stack_distance],eax
        jmp     simple_instruction
pushfw_instruction:
        add     [stack_distance],2
        jmp     simple_instruction_16bit
pushfd_instruction:
        add     [stack_distance],4
        jmp     simple_instruction_32bit_except64
pushfq_instruction:
        add     [stack_distance],8
        jmp     simple_instruction_only64
popfw_instruction:
        sub     [stack_distance],2
        jmp     simple_instruction_16bit
popf_instruction:
        movzx   eax,[code_type]
        shr     eax,3
        sub     [stack_distance],eax
        jmp     simple_instruction
popfd_instruction:
        sub     [stack_distance],4
        jmp     simple_instruction_32bit_except64
popfq_instruction:
        sub     [stack_distance],8
        jmp     simple_instruction_only64             
...
      xchg_reg_reg_8bit:
        jmp     nomem_instruction_ready

get_stack_distance:
        movzx   eax,[operand_size]
        test    eax,eax
        jnz     stack_distance_resolved
        movzx   eax,[push_size]
        test    eax,eax
        jnz     stack_distance_resolved
        movzx   eax,[code_type]
        shr     eax,3
      stack_distance_resolved:
        ret

push_instruction:                 
...
      push_done:
        call    get_stack_distance
        add     [stack_distance],eax
        lods    byte [esi]
        dec     esi
        cmp     al,0Fh
        je      instruction_assembled
        or      al,al
        jz      instruction_assembled
;        mov     [operand_size],0
;        mov     [operand_flags],0
;        mov     [operand_prefix],0
;        mov     [rex_prefix],0
        and     dword [operand_size],0
        jmp     push_next
pop_instruction:              
...
      pop_done:
        call    get_stack_distance
        sub     [stack_distance],eax
        lods    byte [esi]
        dec     esi
        cmp     al,0Fh
        je      instruction_assembled
        or      al,al
        jz      instruction_assembled
;        mov     [operand_size],0
;        mov     [operand_flags],0
;        mov     [operand_prefix],0
;        mov     [rex_prefix],0
        and     dword [operand_size],0
        jmp     pop_next
      pop_sreg:                              
...
inc_instruction:
        mov     [base_code],al
        lods    byte [esi]
        call    get_size_operator
        cmp     al,10h
        je      inc_reg
        cmp     al,'['
        je      inc_mem
        jne     invalid_operand
      inc_mem:
        call    get_address
        mov     al,[operand_size]
        cmp     al,1
        je      inc_mem_8bit
        jb      inc_mem_nosize
        call    operand_autodetect
        mov     al,0FFh
        xchg    al,[base_code]
        mov     [postbyte_register],al
        jmp     instruction_ready
      inc_mem_nosize:
        call    recoverable_unknown_size
      inc_mem_8bit:
        mov     al,0FEh
        xchg    al,[base_code]
        mov     [postbyte_register],al
        jmp     instruction_ready
      inc_reg:
        lods    byte [esi]
        call    convert_register
        mov     bl,al
        mov     al,0FEh
        xchg    al,[base_code]
        mov     [postbyte_register],al
        mov     al,ah
        cmp     al,1
        je      inc_reg_8bit
        call    operand_autodetect
        cmp     [code_type],64
        je      inc_reg_long_form
        mov     al,[postbyte_register]
        shl     al,3
        add     al,bl
        add     al,40h
        mov     [base_code],al
        call    store_classic_instruction_code
        jmp     instruction_assembled
      inc_reg_long_form:
        inc     [base_code]
      inc_reg_8bit:
        jmp     nomem_instruction_ready      
...
store_classic_instruction_code:
        mov     al,[operand_prefix]
        or      al,al
        jz      operand_prefix_ok
        stos    byte [edi]
      operand_prefix_ok:
        mov     al,[opcode_prefix]
        or      al,al
        jz      opcode_prefix_ok
        stos    byte [edi]
      opcode_prefix_ok:
        mov     al,[rex_prefix]
        test    al,40h
        jz      rex_prefix_ok
        cmp     [code_type],64
        jne     invalid_operand
        test    al,0B0h
        jnz     disallowed_combination_of_registers
        stos    byte [edi]
      rex_prefix_ok:
        mov     al,[base_code]
        stos    byte [edi]
        cmp     al,0Fh
        jne     instruction_code_ok
      store_extended_code:
        mov     al,[extended_code]
        stos    byte [edi]
        cmp     al,38h
        je      store_supplemental_code
        cmp     al,3Ah
        je      store_supplemental_code
      instruction_code_ok:
        ret
      store_supplemental_code:
        mov     al,[supplemental_code]
        stos    byte [edi]
        ret                             
store_nomem_instruction:
        test    [postbyte_register],10000b
        jz      nomem_reg_high_code_ok
        or      [vex_required],10h
        and     [postbyte_register],1111b
      nomem_reg_high_code_ok:
        test    [postbyte_register],1000b
        jz      nomem_reg_code_ok
        or      [rex_prefix],44h
        and     [postbyte_register],111b
      nomem_reg_code_ok:
        test    bl,10000b
        jz      nomem_rm_high_code_ok
        or      [rex_prefix],42h
        or      [vex_required],8
        and     bl,1111b
      nomem_rm_high_code_ok:
        test    bl,1000b
        jz      nomem_rm_code_ok
        or      [rex_prefix],41h
        and     bl,111b
      nomem_rm_code_ok:
        and     [displacement_compression],0
        call    store_instruction_code
        mov     al,[postbyte_register]
        shl     al,3
        or      al,bl
        or      al,11000000b

        cmp     [base_code],$FF
        jnz     nomem_add_sub
        mov     edx,1
        cmp     al,$C4
        jz      nomem_add_sp
        cmp     al,$CC
        jmp     nomem_sub_sp
      nomem_add_sub:
        mov     ah, $83
        xor     ah,[base_code]
        test    ah, not 2
        jnz     nomem_notrace
        cmp     al, $C4
        jz      nomem_add_sp
        cmp     al, $EC
      nomem_sub_sp:
        jnz     nomem_notrace
        add     [stack_distance],edx
        jmp     nomem_notrace
      nomem_add_sp:
        sub     [stack_distance],edx
        jmp     nomem_notrace
      nomem_notrace:

        stos    byte [edi]
        ret
store_instruction:    
...
    

testsequence:
Code:
stackorg 16;10
;pusha
;push ax dword 0 eax
use64
;pop rax qword[0] ;ds
;sub sp,3
inc sp
popf
display (%s+'0') and $FF     

stack traced via any combination of pushes & popes, pusha\pushf & popa\popf, sub sp/esp/rsp,imm, add sp/esp/rsp,imm. but inc/dec sp/esp/rsp affected only via 64bit that handled with store_nomem_instruction, how by analogy patch store_classic_instruction_code?

[POST EDITED]
fixes:
EXPRCALC.INC: make %s truly qword with proper sign
Code:
      stacktrace_label:
        mov     eax,[stack_distance]
        cdq
        mov     byte[edi+13],dl
        jmp     make_qword_label_value    


X86_64.INC: accept non x64 mode too for tracing stack predictible changes for inc/dec instructions (cut off actions with register operand_size not accorded to current code_type)
Code:
      inc_reg:
        lods    byte [esi]
        call    convert_register
        mov     bl,al
        mov     al,0FEh
        xchg    al,[base_code]
        mov     [postbyte_register],al
        mov     al,ah
        cmp     al,1
        je      inc_reg_8bit
        call    operand_autodetect
        cmp     [code_type],64
        je      inc_reg_long_form
        mov     al,[postbyte_register]
        shl     al,3
        add     al,bl
        add     al,40h
        mov     [base_code],al
        call    store_classic_instruction_code
        mov     al,$80
        add     al,[base_code]
        jmp     inc_reg_stack_trace
      inc_reg_long_form:
        inc     [base_code]
      inc_reg_8bit:
        call    store_nomem_instruction
      inc_reg_stack_trace:
        mov     ah,[operand_size]
        shl     ah,3
        cmp     ah,[code_type]
        jne     instruction_assembled
        cmp     al,$C4
        je      inc_sp
        cmp     al,$CC
        je      dec_sp
        jmp     instruction_assembled
      inc_sp:
        dec     [stack_distance]
        jmp     instruction_assembled
      dec_sp:
        inc     [stack_distance]
        jmp     instruction_assembled
...
      nomem_rm_code_ok:
        and     [displacement_compression],0
        call    store_instruction_code
        mov     al,[postbyte_register]
        shl     al,3
        or      al,bl
        or      al,11000000b
        stos    byte [edi]

        mov     ah, $83
        xor     ah,[base_code]
        test    ah, not 2
        jnz     nomem_notrace
        mov     ah,[operand_size]
        shl     ah,3
        cmp     ah,[code_type]
        jne     nomem_notrace
        cmp     al, $C4
        jz      nomem_add_sp
        cmp     al, $EC
      nomem_sub_sp:
        jnz     nomem_notrace
        add     [stack_distance],edx
        jmp     nomem_notrace
      nomem_add_sp:
        sub     [stack_distance],edx
        jmp     nomem_notrace
      nomem_notrace:

        ret
store_instruction:
...    


Last edited by ProMiNick on 16 Feb 2023, 11:46; edited 1 time in total
Post 16 Feb 2023, 00:55
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20357
Location: In your JS exploiting you and your system
revolution 16 Feb 2023, 05:39
If you use a comma separator then you can process arguments one by one in a macro.
Code:
macro oush [arg] {
  forward
  ;...
}
push 0, eax, 4+2*7, addr ebx+3, -42    
Then you don't have to alter the assembler code.
Post 16 Feb 2023, 05:39
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.