Печати, какие флаги процессора устанавливаются в начале программы


Это мой первый "настоящий" программы для архитектуры x86, разработанной с нуля. Прошу критики:

format PE console
entry start

include 'win32a.inc'

section '.text' code executable
start:  pushf
        push hello
        call [printf]
        pop ecx
        pop eax
check_carry_flag:
        mov dx, ax ; ax has flags reg
        test ax, 1h 
        jnz carry_flag_set
        mov esi, edx
check_parity_flag:
        mov eax, esi
        test ax, 4h
        jnz parity_flag_set
        mov esi, edx
check_aux_flag:
        mov eax, esi
        test ax, 10h
        jnz aux_flag_set
        mov esi, edx
check_zero_flag:
        mov eax, esi
        test ax, 40h
        jnz zero_flag_set
        mov esi, edx
check_sign_flag:
        mov eax, esi
        test ax, 80h
        jnz sign_flag_set
        mov esi, edx
check_dir_flag:
        mov eax, esi
        test ax, 400h
        jnz dir_flag_set
        mov esi, edx
check_OF_flag:
        mov eax, esi
        test ax, 800h
        jnz OF_flag_set
jmp endme

carry_flag_set:
        mov esi, edx
        push carry_flag
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_parity_flag
parity_flag_set:
        mov esi, edx
        push parity_flag
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_aux_flag
aux_flag_set:
        mov esi, edx
        push aux_flag
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_zero_flag
zero_flag_set:
        mov esi, edx
        push zero_flag
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_sign_flag
sign_flag_set:
        mov esi, edx
        push sign_flag
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_dir_flag
dir_flag_set:
        mov esi, edx
        push dir_flag_set
        call [printf]
        pop ecx
        mov edx, esi
        jmp check_OF_flag
OF_flag_set:
        mov esi, edx
        push OF_flag
        call [printf]
        pop ecx
endme:
        push p
        call [system]
        pop ecx

        push 0
        call [ExitProcess]
section '.rdata' data readable
        hello db 'The flags are: %X', 10, 0
        p db 'pause>nul'
        carry_flag db 'Carry flag set', 0
        parity_flag db 'Parity flag set', 0
        zero_flag db 'Zero flag set', 0
        sign_flag db 'Sign flag set', 0
        dir_flag db 'Direction flag set', 0
        OF_flag db 'Overflow flag set', 0
        aux_flag db 'Aux flag set', 0

section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess'
        import msvcrt, printf, 'printf', \
        system, 'system'


119
5
задан 4 марта 2018 в 02:03 Источник Поделиться
Комментарии
1 ответ

У вас есть немного дублирования кода, которые могут и должны быть удалены, чтобы избежать ошибок. ФАСМ поддерживает макросы, которые можно использовать для удаления повторяющихся частей.

Можно определить check_flag макрос:

macro check_flag op1, op2
{
local flag_not_set
test eax, op1
jz flag_not_set
push eax
push op2
call [printf]
pop eax
pop eax
flag_not_set:
}

Немного объяснений. Этот макрос будет делать ВСЮ работу, которая требуется, чтобы проверить, если конкретный флаг (указанного в качестве операнда OP1) и если так печатать сообщения, указанного операндом оп2. Мы должны указать также на нашем лейбле, как местных, так что нет дублирования, когда макрос помещается в несколько раз код. Мы также держат флаги, чтобы быть восстановлены после печати.

Имея это, мы можем упростить код немного, в основном это:

    check_flag 1h, carry_flag
check_flag 4h, parity_flag
check_flag 10h, aux_flag
check_flag 40h, zero_flag
check_flag 80h, sign_flag
check_flag 400h, dir_flag
check_flag 800h, OF_flag

Что такой подход легко добавить новых, просто написав:

    check_flag 200h, interrupt_flag

Вы также можете добавить новую строку, чтобы эти строки так, что они немного отделены друг от друга при печати, как это:

  aux_flag db 'Aux flag set', 13, 10, 0 

Вся программа:

format PE console
entry start

include 'win32a.inc'

section '.text' code executable

macro check_flag op1, op2
{
local flag_not_set
test eax, op1
jz flag_not_set
push eax
push op2
call [printf]
pop eax
pop eax
flag_not_set:
}

start: pushf
push hello
call [printf]
pop ecx
pop eax

check_flag 1h, carry_flag
check_flag 4h, parity_flag
check_flag 10h, aux_flag
check_flag 40h, zero_flag
check_flag 80h, sign_flag
check_flag 400h, dir_flag
check_flag 800h, OF_flag

push p
call [system]
pop ecx

push 0
call [ExitProcess]

section '.rdata' data readable
hello db 'The flags are: %X', 10, 0
p db 'pause>nul'
carry_flag db 'Carry flag set', 13,10,0
parity_flag db 'Parity flag set',13,10, 0
zero_flag db 'Zero flag set',13,10, 0
sign_flag db 'Sign flag set',13,10, 0
dir_flag db 'Direction flag set',13,10, 0
OF_flag db 'Overflow flag set',13,10, 0
aux_flag db 'Aux flag set',13,10, 0

section '.idata' data readable import
library kernel32, 'kernel32.dll', \
msvcrt, 'msvcrt.dll'
import kernel32, ExitProcess, 'ExitProcess'
import msvcrt, printf, 'printf', \
system, 'system'

3
ответ дан 4 марта 2018 в 06:03 Источник Поделиться