Не могу понять, как напечатать число в MASM32

Я ненавижу задавать такие элементарные вопросы. Это выглядит так, как будто я ленивый! Но я часами просматривал документацию, и по какой-то причине у меня не закружилась голова по этому маленькому вопросу.

Я хочу вывести на экран символ "4". Я могу сделать это как строку, но не из значения ascii.

Вот рабочий код:

include c:\masm32\include\masm32rt.inc
.data
    num4 db "4", 10,0
.code
start:
    invoke StdOut, addr num4
    inkey
    invoke ExitProcess, 0
end start

Я просто хотел сделать маленький шаг оттуда и напечатать 52-й символ ascii (то есть «4»). Вот моя лучшая попытка:

include c:\masm32\include\masm32rt.inc
.data
.code
start:
    myvar db 52
    invoke StdOut, myvar
    inkey
    invoke ExitProcess, 0
end start

Он собирается и связывается без проблем, но затем вылетает, когда я его запускаю. Я знаю, что в конце нет символа 0, но invoke StdOut, myvar,0 имеет слишком много аргументов для StdOut.

Моя конечная цель - напечатать многозначное число, как описано Алексеем Фрунзе здесь:

сборка x86 (masm32) - как разделить многозначные данные на отдельные символы

Но так как у меня так много проблем с синтаксисом, я делаю маленькие шаги. Я нашел это, но это не объясняет, как синтаксически добавить часть 48:

сборка x86 - как показать целое число 2, а не второй символ ASCII

Пожалуйста, помогите мне преодолеть эти начальные препятствия, и спасибо!


person Ben I.    schedule 05.02.2015    source источник


Ответы (1)


Во-первых, myvar db 52 находится не в том месте. Когда программа запускается, компьютер переходит к db 52 и воспринимает это как инструкцию. Во-вторых, значение 0 (не говорите символ) не является аргументом для StdOut и должно быть в конце данных. StdOut в качестве аргумента требуется указатель на строку, заканчивающуюся нулем. Вы не можете дать ему прямое значение, функция тем не менее воспримет это как указатель. Кстати: учтите, что StdOut — это функция MASM32, а не функция ядра Windows. Ваша программа должна выглядеть так:

include c:\masm32\include\masm32rt.inc
.data
    myvar db 52, 0
.code
start:
    invoke StdOut, ADDR myvar
    inkey
    invoke ExitProcess, 0
end start

Вы должны сначала создать строку, прежде чем выводить ее с помощью «StdOut». Если у вас есть не строка, а число, вы должны преобразовать его в строку (ключевые слова для Google: «сборка преобразовать целое число в ascii»). Хитрость заключается в многократном делении числа на 10 и сохранении остатка. Еще одна хитрость заключается в использовании макроса MASM32.

INCLUDELIB C:\masm32\lib\masm32.lib
INCLUDE C:\masm32\include\masm32rt.inc

.DATA
    decimalstr db 16 DUP (0)
    myvar db 52

.CODE

start PROC

    movzx eax, myvar         ; Load an 8-bit-byte into a 32-bit-register
    lea edi, decimalstr      ; Load the address of decimalstr
    call EAX_to_DEC
    invoke StdOut, addr decimalstr

    movzx eax, myvar
    printf ("\nAnd the lazy MASM32 way: %u\n",eax)

    invoke ExitProcess, 0
start ENDP

EAX_to_DEC PROC             ; ARG: EDI pointer to string buffer
    mov ebx, 10             ; Divisor = 10
    xor ecx, ecx            ; ECX=0 (digit counter)
  @@:                       ; First Loop: store the remainders
    xor edx, edx
    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 @B                  ; no: once more (jump to the first @@ above)
  @@:                       ; 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 @B                 ; until there are no digits left
    mov byte ptr [edi], 0   ; ASCIIZ terminator (0)
    ret                     ; RET: EDI pointer to ASCIIZ-string
EAX_to_DEC ENDP

END start

Также посмотрите здесь.

person rkhb    schedule 05.02.2015
comment
Этот ответ удивителен и дает мне руководство для моей будущей цели (хотя я еще не понимаю всех аспектов этого ответа, но ваши комментарии очень полезны, и я предполагаю, что это придет со временем и настойчивостью). Но у вас также есть ответ на нерабочий код, который я представил? - person Ben I.; 06.02.2015
comment
О, и еще, почему вы объявили clrf? Похоже, он больше нигде не используется. - person Ben I.; 06.02.2015
comment
@Choirbean: Пожалуйста, взгляните на обновленный ответ. Я сделал все возможное :-) - person rkhb; 06.02.2015
comment
Большое спасибо, рхб. Я хотел бы связаться с вами за пределами сайта с другими вопросами - вы очень ясны. Это было невероятно! - person Ben I.; 06.02.2015