Задать вопрос
@gregoryhouse963

Как написать ассембли код x86 nasm для Linux?

660ebd42f2ae8266756075.png
Мне нужно написать ассембли код x86 nasm для Linux, чтобы решить эту проблему. Необходимо создать список из 55 учеников, каждый из которых имеет свою оценку. Программе необходимо распечатать имя ученика с наивысшей оценкой, а также поставить рядом с ним его оценку. Если есть несколько учеников с одинаковым наивысшим баллом, необходимо вывести имя студента, который стоит первым в списке.
Код который я написал, но еще не закончил доконца:
section .data
    ; Student records
    students:
        db "John      ", 80         ; Student 1: Name "John", Mark 80
        db "Alice     ", 70         ; Student 2: Name "Alice", Mark 70
        db "Bob       ", 80         ; Student 3: Name "Bob", Mark 80
        ; Add more students as needed

    new_line db 10, 0  ; Define newline character

section .text
    global _start

_start:
    ; Initialize registers
    mov eax, students        ; Start of student records
    mov ecx, 55             ; Number of students
    mov edx, 0              ; Initialize maximum mark
    xor ebx, ebx            ; Initialize index of max mark student
    xor edi, edi            ; Initialize index of first max mark student

traverse_loop:
    ; Load student name
    mov esi, eax
    call PrintName

    ; Load and print student mark
    movzx esi, byte [eax + 10h]  ; Load the module mark
    call PrintMark

    ; Compare marks
    cmp esi, edx                   ; Compare with current maximum mark
    jle not_greater               ; If not greater, skip
    mov edx, esi                    ; Update maximum mark
    mov edi, ebx                  ; Update index of first max mark student
not_greater:
    add eax, 11                  ; Move to the next student record

    inc ebx                        ; Increment index
    dec ecx                        ; Decrement counter
    jnz traverse_loop             ; If not zero, continue traversal

    ; Return with the first student with the highest mark
    mov eax, students
    add eax, edi                   ; Calculate address of the first max mark student

    ; Print a new line
    mov eax, 4              ; sys_write system call
    mov ebx, 1              ; File descriptor for stdout
    mov ecx, new_line       ; Address of newline
    mov edx, 1              ; Length of newline
    int 0x80                ; Call kernel

    ; Exit
    mov eax, 1              ; syscall number for exit
    xor ebx, ebx            ; exit code 0
    int 0x80                ; call kernel

PrintName:
    ; Print student name
    mov eax, 4                    ; sys_write system call
    mov ebx, 1                    ; File descriptor for stdout
    mov ecx, esi                  ; Address of student name
    mov edx, 10                  ; Length of student name
    int 0x80                      ; Call kernel
    ret

PrintMark:
    ; Print student mark
    mov eax, 4                    ; sys_write system call
    mov ebx, 1                    ; File descriptor for stdout
    mov ecx, eax                  ; Address of student record
    add ecx, 10h                  ; Offset to mark
    mov edx, 2                    ; Length of student mark
    int 0x80                      ; Call kernel
    ret

После того как я раню код мне выдается слелующее:
John Segmentation fault
Как видно, John выходит верно, но вместо отметки рядом с ним я получаю Segmentation fault
  • Вопрос задан
  • 2134 просмотра
Подписаться 4 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 3
@Ava256
долгий путь в тех. поддержке
Видимо ошибка ф функции PrintMark.

Перед вызовом ты грузишь значение отметки в si, но в вызове его не используешь.Зачем-то копируешь там из EAX, хотя до этого записал туда 4, зачем-то еще раз берешь offset,
Ответ написан
Комментировать
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Твой traverse_loop держит указатель на текущую запись в eax, но первый же вызов PrintName портит почти все регистры и не восстанавливает их, поэтому первый же movzx esi, byte [eax + 10h] после этого вызова обращается мимо памяти и вызывает segfault. Проще всего это исправить каким-нибудь pusha / popa вокруг тела PrintName. После этого ты доберёшься до вызова PrintMark, где увидишь, что эта функция ожидает в eax + 10h текстового представления оценки, а у тебя пока есть только двоичное.
Ответ написан
Комментировать
mindtester
@mindtester
http://iczin.su/hexagram_48
int 0x80 ; Call kernel
доки то читал?

ps аж ностальгия..
но не в твою пользу..
section .data только грусть вызывает..
.. и да... если тебе не хватает регистров для данных..
section .data не только для списка других... кхм... пытающихся стать программистами ))
... желаю успеха, но придется включить свои мозги... без вариантов
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы