.section .note.GNU-stack,"",@progbits
.section .data
cf_msg:
.string "CF = %d\n"
of_msg:
.string "OF = %d\n"
sf_msg:
.string "SF = %d\n"
less_msg:
.string "a less than b"
not_less_msg:
.string "a not less than b"
below_msg:
.string "a below b\n"
not_below_msg:
.string "a not below b\n"
.section .text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
# Pair 1: 53 and 25
movb $53, %dil
movb $25, %sil
call check_flags_and_compare
call clear_flags
# Pair 2: 53 and 91
movb $53, %dil
movb $91, %sil
call check_flags_and_compare
call clear_flags
# Pair 3: 53 and -43
movb $53, %dil
movb $-43, %sil
call check_flags_and_compare
call clear_flags
# Pair 4: -98 and -45
movb $-98, %dil
movb $-45, %sil
call check_flags_and_compare
movq $0, %rax
popq %rbp
ret
check_flags_and_compare:
pushq %rbp
movq %rsp, %rbp
# Arguments: %dil (a), %sil (b)
# Preserve arguments
movb %dil, %r8b
movb %sil, %r9b
# Perform addition to set flags
movb %r8b, %al
addb %r9b, %al
# Store flags
setc %r12b
seto %r13b
sets %r14b
# Print CF
movq $cf_msg, %rdi
movzbq %r12b, %rsi
call printf
# Print OF
movq $of_msg, %rdi
movzbq %r13b, %rsi
call printf
# Print SF
movq $sf_msg, %rdi
movzbq %r14b, %rsi
call printf
# Compare signed
cmpb %r9b, %r8b
jl signed_less
movq $not_less_msg, %rdi
call puts
jmp signed_done
signed_less:
movq $less_msg, %rdi
call puts
signed_done:
movb %dil, %r8b
movb %sil, %r9b
# Compare unsigned
cmpb %r9b, %r8b
jb unsigned_below
movq $not_below_msg, %rdi
call puts
jmp unsigned_done
unsigned_below:
movq $below_msg, %rdi
call puts
unsigned_done:
popq %rbp
ret
clear_flags:
xor %eax, %eax # Clear SF
clc # Clear CF
movb $0, %al
add %al, %al # Clear OF
ret
Это результат, который я получаю (флаги должны быть в порядке):
КФ = 0, ОФ = 0, СФ = 0,
а меньше, чем б, а не ниже б
КФ = 0, ОФ = 1, СФ = 1, а меньше, чем б, а не ниже б,
КФ = 1, ОФ = 0, СФ = 0, а меньше, чем б, а не ниже б,
КФ = 1, ОФ = 1, СФ = 0, а меньше, чем б, а не ниже б,
Вот как это должно выглядеть, имхо:
КФ = 0, ОФ = 0, СФ = 0,
а не менее б, а не ниже б,
КФ = 0, ОФ = 1, СФ = 1,
а меньше, чем б, а ниже б,
КФ = 1, ОФ = 0, СФ = 0,
а не менее б, а ниже б,
КФ = 1 ОФ = 1 СФ = 0
а меньше чем б а ниже б
Вы не указали ОС, но исходя из использования GAS и вашего соглашения о вызовах, я предполагаю, что это GNU/Linux.
В соглашении о вызовах SYSV, используемом для Linux x86-64, r8 и r9 являются регистрами, сохраняемыми вызывающей стороной, то есть они не сохраняются при вызове функции. Вы сохраняете аргументы check_flags_and_compare
в r8 и r9, а затем вызываете printf, который, скорее всего, перезапишет эти регистры.
Рассмотрите возможность использования разных регистров или переменных стека.
Обратите внимание, что в соглашении о вызовах SYSV только rbx, rsp, rbp, r12, r13, r14 и r15 являются регистрами, сохраняемыми вызываемым абонентом (сохраняются при вызове функции); все остальные сохраняются для вызывающего абонента. rsp автоматически сохраняется в силу того, что стек должен быть сбалансирован при входе и выходе; остальные регистры должны быть сохранены и восстановлены любой функцией, которая их изменяет.
Таким образом, вам также следует сохранять и восстанавливать значения r12-r14 в вашей функции, поскольку вы их изменяете, чтобы соблюдать ABI; если вы не сохраните их и ваша функция будет вызвана функцией C, могут возникнуть странные и трудные для отладки ошибки.
r8
иr9
не сохраняются между вызовами, что означает, чтоprintf
вполне может изменить их к моменту сравнения. И наоборот,r12
-r15
следует сохранить, но вы этого не делаете.