Запись значения, определенного с помощью EQU, в консоль с помощью системных вызовов Linux


Для записи в консоль текста, на который указывает какая-то метка, я использую следующий код:

section .data                           ;Data segment
   userMsg db 'Please enter a number: ' ;Ask the user to enter a number
   lenUserMsg equ $-userMsg             ;The length of the message             


section .text          ;Code Segment
   global _start

_start:                
   ;User prompt
   mov eax, 4
   mov ebx, 1
   mov ecx, userMsg
   mov edx, lenUserMsg
   int 80h

   ; Exit code
   mov eax, 1
   mov ebx, 0
   int 80h

Но что делать, если я хочу записать в консоль значение, хранящееся под значением lenUserMsg ?

Я попробовал ниже:

   ...
   ;User prompt
   mov eax, 4
   mov ebx, 1
   mov ecx, lenUserMsg
   mov edx, 1
   int 80h
   ...

Он компилируется и запускается без сбоев, но ничего не записывает в консоль.

1 2

1 ответ:

lenUserMsg не хранится. Директива EQU делает его просто макросом, значение которого (строка!) рассчитывается в момент сборки и заменяет собой любое появление его "имени". Нет никаких шансов получить его значение во время выполнения. Если вам нужно значение, которое хранится в разделе .data, Вы можете определить его как любое другое значение - в скобках. Я предполагаю, что вы хотите видеть десятичное представление lenUserMsg, так как Int 80h/EAX=4 только печатает строки, поэтому я добавил процедуру преобразования следующим образом пример:

section .data                            ;Data segment
    userMsg db 'Please enter a number: ' ;Ask the user to enter a number
    lenUserMsg dd $-userMsg              ;The length of the message

section .bss
    buf resb 16

section .text          ;Code Segment
global _start

_start:
    ;User prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, userMsg
    mov edx, [lenUserMsg]
    int 80h

    mov eax, [lenUserMsg]
    mov edi, buf
    call EAX_to_DEC

    mov edx, eax
    mov ecx, buf
    mov ebx, 1
    mov eax, 4
    int 80h

    ; Exit code
    mov eax, 1
    mov ebx, 0
    int 80h

EAX_to_DEC:                     ; ARG: EDI pointer to string buffer
    mov ebx, 10                 ; Divisor = 10
    xor ecx, ecx                ; ECX=0 (digit counter)
    .L1:                        ; First Loop: store the remainders
    xor edx, edx                ; Don't forget it!
    div ebx                     ; EDX:EAX / EBX = EAX remainder EDX
    push dx                     ; Push the digit in DL (LIFO)
    add cl, 1                   ; = inc cl (digit counter)
    or eax, eax                 ; AX == 0?
    jnz .L1                     ; No: once more (jump to the first @@ above)
    mov ebx, ecx                ; Store count of digits
    .L2:                        ; Second loop: load the remainders in reversed order
    pop ax                      ; get back pushed digits
    or al, 00110000b            ; to ASCII
    stosb                       ; Store AL to [EDI] (EDI is a pointer to a buffer)
    loop .L2                    ; until there are no digits left
    mov eax, ebx                ; Restore Count of digits
    ret                         ; RET: EAX length of string