1

我被赋予了以下任务:

给定两个具有 16 个元素的数组:NIZA RESW 16 和 NIZB RESW 16
在第三个数组 (NIZC RESW 16) 中存储以下值:NIZC[i]=NIZA[i]+NIZB[i] 使用 MMX 指令并使用 NASM 编译它

这是我到目前为止得到的:

%include "apicall.inc"
%include "print.inc"

segment .data
unos1 db "Array A: ", 0
unos2 db "Array B: ", 0
ispisC db "Array C : ", 0

segment .bss
  NIZA RESW 16
  NIZB RESW 16
  NIZC RESW 16

segment .text
global start

start:
call init_console
mov esi,0
mov ecx, 16

mov eax, unos1
call print_string
call print_nl

unos_a:
call read_int
mov [NIZA+esi], eax
add esi, 2
loop unos_a

mov esi,0
mov ecx, 16
mov eax, unos2
call print_string
call print_nl

unos_b:
call read_int
mov [NIZB+esi], eax
add esi, 2
loop unos_b

movq mm0, qword [NIZA]
movq mm1, qword [NIZB]
paddq mm0, mm1
movq qword [NIZC], mm0


mov esi,NIZC
mov ecx,16
mov eax, ispisC
call print_string
call print_nl

ispis_c:
mov ax, [esi]
movsx eax, ax
call print_int
call print_nl
add esi, 2
loop ispis_c

APICALL ExitProcess, 0

编译给定数组后,并用以下两个数组对其进行测试,第三个数组仅存储 16 个元素中的 4 个。(如下图所示)

截屏

有人知道为什么它只存储 16 个元素中的 4 个吗?任何帮助表示赞赏。
如果您对函数有任何疑问,这些函数print_string print_int print_nl是通过将字符串压入 EAX 寄存器来打印出字符串、换行符和整数的函数,还要注意这是一个 32 位程序。

4

1 回答 1

2

有人知道为什么它只存储 16 个元素中的 4 个吗?

因为您让 MMX 指令仅对前 4 个数组元素进行操作。您需要一个循环来处理所有 16 个数组元素。

您的任务描述没有说明,但我看到您在打印之前对NIZC的值进行了符号扩展,因此您似乎期待签名结果。我还看到您使用PADDQ4 个字大小的输入进行操作。这将不会总是给出正确的结果!例如。如果NIZA[0]=-1NIZB[0]=5,那么你会得到NIZC[0]=4,但是会发生从第一个单词到第二个单词的进位,留下NIZC[1]错误。如果您使用正确版本的打包添加,则不会发生这种情况:PADDW.

你很幸运在mov [NIZA+esi], eax和上出现尺寸错误mov [NIZB+esi], eax。因为NIZANIZB在内存中的顺序与您分配给它们的顺序相同,所以没有造成任何伤害。如果NIZB被放置在NIZA之前,那么分配NIZB[15]将损坏NIZA[0]

下面是部分重写,其中我使用了输入子例程,以便不必重复自己

    mov   eax, unos1
    mov   ebx, NIZA
    call  MyInput
    mov   eax, unos2
    mov   ebx, NIZB
    call  MyInput

    xor   esi, esi
more:
    movq  mm0, qword [NIZA + esi]
    paddw mm0, qword [NIZB + esi]
    movq  qword [NIZC + esi], mm0
    add   esi, 8
    cmp   esi, 32
    jb    more
    emms                     ; (*)

    ...


MyInput:
    call  print_string
    call  print_nl
    xor   esi, esi
  .more:
    call  read_int           ; -> EAX
    mov   [ebx + esi], ax
    add   esi, 2
    cmp   esi, 32            ; Repeat 16 times
    jb    .more
    ret

(*) 有关emms(空 MMX 状态)的信息,请参阅https://www.felixcloutier.com/x86/emms

mov ax, [esi] movsx eax, ax提示:您可以在一条指令中编写: movsx eax, word [esi].

于 2021-11-24T23:41:17.453 回答