2014-01-19 7 views
2

Я использую MUL в сборке (MASM), чтобы умножить два целых числа.Как распечатать вывод продукта MUL?

В соответствии с инструкциями по установке MASM, продукт хранится в EDX: EAX, комбинация регистров EDX и EAX (если я правильно понимаю).

Итак, я попробую распечатать результат регистрации EDX, а затем регистр EAX, чтобы распечатать все число.

Но когда я получаю продукт, который предположительно превышает 32 бита (10 знаков после запятой), я получаю странный ответ.

Например, 100000 * 100000 = 21410065408, что не так. Но для небольших умножений он работает.

Вот код сборки:

; MULTIPLY 
    mov eax, var1 ; var1 and var2 from user input 
    mul var2 
    mov productResultEDX, edx 
    mov productResultEAX, eax 


; PRINT RESULT 
; mov edx, OFFSET productMsg 
    call WriteString 
    mov eax, productResultEDX 
    call WriteDec ; prints out EAX register data 
    ;mov eax, productResultEAX 
    ;call WriteDec 

Все переменные объявлены как 32 бит DWORDs

ли я приближается это неправильно?

+0

Обратите внимание, что младший 32 битом 100000 * 100000 является десятичным значением 1410065408. верхним 32 бит десятичного значение 2. Это объясняет свой результат, хотя я не уверен, как вы бы исправить ваш код, чтобы показать правильный результат. – icktoofay

+0

Хм, что вы подразумеваете под объяснением моего результата? – LazerSharks

+0

Вы печатаете десятичное значение верхних 32 бит, 2. Затем вы печатаете десятичное значение нижних 32 бит, 1410065408. Разбейте их вместе. 21410065408, ваш результат. Вы не можете просто печатать их сразу за другим; вы получите бессмысленные результаты. – icktoofay

ответ

3

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

Итак, если вы не хотите выписывать свою собственную 64-битную процедуру печати по номеру, просто используйте функцию c printf, masm32 называет ее crt_printf.

Вы можете создать переменную qword для хранения edx: eax или использовать структуру.

include masm32rt.inc 
include msvcrt.inc 
includelib msvcrt.lib 

BigNum struc 
    LoWord dd ? 
    HiWord dd ? 
BigNum ends 

.data 
fmtqw1  db "100000 * 100000 = %llu",13, 10, 0 
fmtqw2  db "400030 * 500020 = %llu",13, 10, 0 

.data? 
myqword  dq ? 
BigNumber BigNum <> 

.code 
start: 

    mov  eax, 100000 
    mov  ecx, 100000 
    mul  ecx 
    mov  dword ptr[myqword], eax 
    mov  dword ptr[myqword + 4], edx 
    invoke crt_printf, offset fmtqw1, myqword 

    mov  eax, 400030 
    mov  ecx, 500020 
    mul  ecx  
    mov  BigNumber.LoWord, eax 
    mov  BigNumber.HiWord, edx 
    invoke crt_printf, offset fmtqw2, BigNumber 

    inkey 
    invoke ExitProcess, 0 
end start 

64 bit mul results

+0

Ах, я вижу. Да, я действительно использую библиотеку Irvine32, и я действительно забыл о том, что в процедуре WriteDec, которую я использовал, записываются только 32-битные целые числа. Хотя я бы подумал, что произведение двух 32-битных целых чисел будет разбито на 32-битный регистр EDX и 32-битный регистр EAX. Большой улов, спасибо. – LazerSharks

1

Вы делаете это арифметика: 100000 * 100000.

Мы все надеемся, что ответ 10000000000 (Десять миллиардов)

Теперь, так получилось, что десять миллиардов, в гекс,

2 540B E400

Моя догадка (полностью предполагаю здесь), что ваши WriteString и WriteDec процедуры не знают, что у вас может быть большой (64-разрядный) номер, который вы пытаетесь распечатать

Это может помочь прояснить некоторые моменты ...

Десять миллиардов это 2 540B E400

Нижние 32 бита, которые являются: 540B E400

Это значение, в десятичной системе, является: 1410065408

Это значение, если вы предварять цифру 2, это ваше неправильный ответ, то есть, 21,410,065,408

Вот предлагаемый тест

Используйте свой существующий код, чтобы умножить эти два числа ...

286,331,153 * 15 и вы должны получить 4,294,967,295 что один меньше, чем 4 Gig

Теперь увеличить первое число на 1, и сделать умножение снова; то есть

286,331,153 * 15 и вы должны получить 4,294,967,310 (т. е. на 15 больше, чем в первый раз).

Если ваша программа показывает, что ответ 115, вы прибиваете ошибку.

Вот что происходит.

286,331,153 * 15 также 1111,1111h * 0000,000Fh

(запятые предназначены для ясности только чтение)

Продукт FFFF,FFFFH или четыре концерта (минус один) число раз упоминается

сейчас то, случается так, что если мы увеличим число на один, вот так

286,331,154 * 15

Теперь у нас есть

1111,1112h * 0000,000Fh

С результатом: 1 0000 000E

Таким образом, если ожидается десятичное число 4,294,967,310 фактически показывает, как 115, вы нашли ошибку.

1

Это то, что я использую. Это НЕ оптимально! Синтаксис Nasm, может потребоваться незначительное изменение для Masm. Подстройте его в соответствии с вашими потребностями.

; ---------------------------------------- 
; u64toda - converts (64 bit) integer in edx:eax 
; to (comma delimited) decimal representation in 
; ascii zero terminated string in buffer pointed to by edi 
;-------------------------------------------- 
u64toda: 
      pusha 
      mov ebx, edx  ; stash high dword 
      mov esi,0Ah  ; prepare to divide by 10 
      xor ecx, ecx  ; zero the digit count 
      jmp highleft  ; check is high word 0 ? 
highword: 
      xchg eax,ebx ; swap high & low words 
      xor edx,edx  ; zero edx for the divide! 
      div esi   ; divide high word by 10 
      xchg eax,ebx ; swap 'em back 
      div esi   ; divide low word including remainder 
      push edx  ; remainder is our digit - save it 
      inc ecx   ; count digits 
highleft: 
      or ebx,ebx 
      jnz highword 
lowleft: 
      xor edx,edx   ; zero high word 
      div esi    ; divide low word by 10 
      push edx    ; our digit 
      inc ecx    ; count it 
      or eax,eax   ; 0 yet ? 
      jne lowleft 
      cmp ecx, byte 4  ; commas needed ? 
      jl write2buf   ; nope 
      xor edx,edx   ; zero high word for divide 
      mov eax,ecx   ; number of digits 
      mov ebx,3 
      div ebx 
      mov esi,edx   ; remainder = number digits before comma 
      test edx,edx 
      jnz write2buf  ; no remainder? 
      mov esi,3    ; we can write 3 digits, then. 
write2buf: 
      pop eax    ; get digit back - in right order 
      add al,30H   ; convert to ascii character 
      stosb    ; write it to our buffer 
      dec esi    ; digits before comma needed 
      jnz moredigits  ; no comma needed yet 
      cmp ecx,2    ; we at the end? 
      jl moredigits  ; don't need comma 
      mov al,','   ; write a comma 
      stosb 
      mov esi,03h   ; we're good for another 3 digits 
moredigits: 
      loop write2buf  ; write more digits - cx of 'em 
      mov al,00h   ; terminate buffer with zero 
      stosb 
    popa 
      ret 
;------------------------------------- 
Смежные вопросы