If-Else в сборке, похоже, не работает или я делаю что-то неправильно

.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

а меньше чем б а ниже б

r8 и r9 не сохраняются между вызовами, что означает, что printf вполне может изменить их к моменту сравнения. И наоборот, r12-r15 следует сохранить, но вы этого не делаете.
Jester 10.06.2024 14:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не указали ОС, но исходя из использования 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, могут возникнуть странные и трудные для отладки ошибки.

Другие вопросы по теме