Как напечатать новую строку после числа в цикле в сборке x86? - PullRequest
1 голос
/ 17 октября 2019

У меня есть программа сборки, которая печатает числа от 1 до 9 в одной строке, например: 123456789. Я хочу напечатать эти значения в одной строке;одно число для каждой строки.

Я пытался реализовать новую строку, но в моем коде выдается ошибка Ошибка сегментации (ядро сброшено). Я все еще очень свеж в сборке, поэтому я не знаю, как выяснить, почему это не работает. Он печатает только первое число (1), а затем выдает эту ошибку.

Код, который я пробовал для новой строки:

mov dl, 13
mov ah, 02h
int 21h
mov dl, 10
mov ah, 02h
int 21h

мой код:

_start:
    mov ecx, 10
    mov eax, '1'

L1:
    mov [num], eax
    mov eax, 4
    mov ebx, 1
    push ecx

    mov ecx, num
    mov edx, 1
    int 0x80

    mov eax, [num]
    sub eax, '0'
    inc eax
    add eax, '0'
    pop ecx
    loop L1

    mov eax, 1
    int 0x80

section .bss
    num resb 1

1 Ответ

2 голосов
/ 17 октября 2019

Вы должны использовать тот же системный вызов для печати новой строки, которую используете для печати чисел.

Кроме того, новая строка в Linux - это просто LF (char 10,), а не CR (char 13)затем LF, как в Windows / DOS.

Как печатать на стандартный вывод в Linux в сборке x86

Этот ответ описывает действия каждого из аргументов для печати Linuxсистемный вызов, который вы вызываете, вызывая int 0x80.

Системные вызовы используют регистры для передачи своих аргументов. Из связанного ответа eax - это номер системного вызова (4 = печать), ebx - это поток назначения (1 = стандартный вывод), * ​​1014 * - указатель на данные для печати, а edx - длинаданные для печати. ​​

Итак, код, который фактически выполняет печать в вашем цикле:

mov [num], eax  ; Moves the character in eax to the buffer pointed to by num.
mov eax, 4      ; Moves 4 into eax, i.e. selects the print system call.
mov ebx, 1      ; Moves 1 into ebx, i.e. selects stdout as the destination.
mov ecx, num    ; Moves the address where your text is stored into ecx.
mov edx, 1      ; Moves the number of bytes to characters (1) into edx.
int 0x80        ; Executes a Linux system call using the above parameters.

Чтобы напечатать новую строку, вам просто необходим символ перевода строки(десятичный символ 10) в eax перед этим кодом, а не символ для числа. Так, например, добавление mov eax, 10 перед этим кодом будет печатать перевод строки вместо числа.

Как заставить это работать с вашим существующим циклом

num в вашем "my"секция code »- это буфер, в котором вы храните данные для печати. Однако этот код также использует эту память, чтобы отслеживать последний напечатанный номер. Итак, есть два способа потерять эту информацию между циклами:

Вариант 1: Просто увеличьте размер вашего буфера с 1 байта до 2 и поместите перевод строки во второй байт. Затем вы можете просто переместить 2 в edx вместо 1, чтобы сообщить Linux, что вы хотите напечатать 2 символа, таким образом печатая как число, так и перевод строки на каждой итерации цикла.

Вариант 2. Выделите еще один однобайтовый буфер для хранения перевода строки. Переместите туда символ перевода строки, затем сделайте второй системный вызов после системного вызова, который печатает номер в цикле для печати перевода строки. Если бы ваш новый буфер назывался, например, «lfbuffer», то вы добавили бы этот код после строки int 0x80 в существующем цикле:

mov byte [lfbuffer], 10  ; Moves the a line feed to the buffer pointed to by lfbuffer.
mov eax, 4           ; Moves 4 into eax, i.e. selects the print system call.
mov ebx, 1           ; Moves 1 into ebx, i.e. selects stdout as the destination.
mov ecx, lfbuffer    ; Moves the address where your line feed is stored into ecx.
mov edx, 1           ; Moves the number of bytes to characters (1) into edx.
int 0x80             ; Executes a Linux system call using the above parameters.
...