Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 汇编-输出32位寄存器与16位寄存器的阵列_Arrays_Sorting_Assembly_X86_Irvine32 - Fatal编程技术网

Arrays 汇编-输出32位寄存器与16位寄存器的阵列

Arrays 汇编-输出32位寄存器与16位寄存器的阵列,arrays,sorting,assembly,x86,irvine32,Arrays,Sorting,Assembly,X86,Irvine32,我正在做一些家庭作业来打印一个数组,因为它从数组中排序一些整数。我的代码运行良好,但决定尝试在代码中使用EAX而不是AL,并遇到了错误。我不明白这是为什么。在这里可以使用EAX吗 ; This program sorts an array of signed integers, using ; the Bubble sort algorithm. It invokes a procedure to ; print the elements of the array b

我正在做一些家庭作业来打印一个数组,因为它从数组中排序一些整数。我的代码运行良好,但决定尝试在代码中使用EAX而不是AL,并遇到了错误。我不明白这是为什么。在这里可以使用EAX吗

    ; This program sorts an array of signed integers, using 
    ; the Bubble sort algorithm. It invokes a procedure to 
    ; print the elements of the array before, the bubble sort, 
    ; once during each iteration of the loop, and once at the end.

    INCLUDE Irvine32.inc
    .data
    myArray   BYTE       5, 1, 4, 2, 8
    ;myArray    DWORD       5, 1, 4, 2, 8
    currentArray BYTE   'This is the value of array: ' ,0
    startArray BYTE 'Starting array. ' ,0
    finalArray BYTE 'Final array. ' ,0
    space BYTE ' ',0                                                ; BYTE

    .code
    main PROC

        MOV EAX,0                                       ; clearing registers, moving 0 into each, and initialize
        MOV EBX,0                                       ; clearing registers, moving 0 into each, and initialize
        MOV ECX,0                                       ; clearing registers, moving 0 into each, and initialize
        MOV EDX,0                                       ; clearing registers, moving 0 into each, and initialize
        PUSH EDX                        ; preserves the original edx register value for future writeString call
        MOV EDX, OFFSET startArray  ; load EDX with address of variable
        CALL writeString                ; print string
        POP EDX                         ; return edx to previous stack
        MOV ECX, lengthOf myArray           ; load ECX with # of elements of array
        DEC ECX                               ; decrement count by 1


    L1: 
        PUSH ECX                             ; save outer loop count
        MOV ESI, OFFSET myArray          ; point to first value

    L2: 
        MOV AL,[ESI]              ; get array value
        CMP [ESI+1], AL               ; compare a pair of values
        JGE L3                        ; if [esi] <= [edi], don't exch
        XCHG AL, [ESI+1]             ; exchange the pair
        MOV [ESI], AL
        CALL printArray             ; call printArray function
        CALL crlf
    L3: 
        INC ESI                       ; increment esi to the next value
        LOOP L2                   ; inner loop
        POP ECX                   ; retrieve outer loop count
        LOOP L1                   ; else repeat outer loop
        PUSH EDX                        ; preserves the original edx register value for future writeString call
        MOV EDX, OFFSET finalArray  ; load EDX with address of variable
        CALL writeString                ; print string
        POP EDX                         ; return edx to previous stack
        CALL printArray

    L4 : ret 



    exit
    main ENDP


    printArray PROC uses ESI ECX

    ;myArray loop
        MOV  ESI, OFFSET myArray                                ; address of myArray
        MOV  ECX, LENGTHOF myArray                              ; loop counter (5 values within array)          
        PUSH EDX                        ; preserves the original edx register value for future writeString call
        MOV EDX, OFFSET currentArray    ; load EDX with address of variable
        CALL writeString                ; print string
        POP EDX                         ; return edx to previous stack

    L5 :
        MOV  AL, [ESI]                                              ; add an integer into eax from array
        CALL writeInt   
        PUSH EDX                        ; preserves the original edx register value for future writeString call
        MOV EDX, OFFSET space
        CALL writeString
        POP EDX                         ; restores the original edx register value  
        ADD  ESI, TYPE myArray                                  ; point to next integer     
        LOOP L5                                             ; repeat until ECX = 0 
        CALL crlf

    RET 

        printArray ENDP

        END main
        END printArray

    ; output:
    ;Starting array. This is the value of array: +1 +5 +4 +2 +8

    ;This is the value of array: +1 +4 +5 +2 +8

    ;This is the value of array: +1 +4 +2 +5 +8

    ;This is the value of array: +1 +2 +4 +5 +8

    ;Final array. This is the value of array: +1 +2 +4 +5 +8
;这个程序使用
; 气泡排序算法。它调用一个过程来
; 打印之前数组的元素,气泡排序,
; 在循环的每次迭代中,以及在循环结束时,各执行一次。
包括Irvine32.inc
.数据
myArray字节5,1,4,2,8
;myArray DWORD 5,1,4,2,8
currentArray BYTE'这是数组的值:',0
startArray字节“开始数组”,0
最终数组字节“最终数组”,0
空格字节“”,0;字节
.代码
主进程
MOV-EAX,0;清除寄存器,将0移到每个寄存器中,并初始化
MOV-EBX,0;清除寄存器,将0移到每个寄存器中,并初始化
MOV-ECX,0;清除寄存器,将0移到每个寄存器中,并初始化
MOV-EDX,0;清除寄存器,将0移到每个寄存器中,并初始化
推动EDX;保留原始edx寄存器值以供将来的writeString调用
MOV-EDX,偏移星光;用变量的地址加载EDX
通话记录;打印字符串
POP-EDX;将edx返回到上一个堆栈
MOV ECX,myArray的长度;用数组元素的#加载ECX
DEC-ECX;递减计数1
L1:
推动ECX;保存外循环计数
MOV ESI,偏移量myArray;指向第一个值
L2:
MOV AL[ESI];获取数组值
CMP[ESI+1],AL;比较一对值

JGE-L3;如果[esi]如果仍要进行8位存储,则需要使用8位寄存器。(AL是一个8位寄存器。IDK为什么在标题中提到16)

x86具有加宽的负载(
movzx
movsx
),但来自寄存器操作数的整数存储始终采用与内存操作数相同宽度的寄存器。i、 e.存储EAX低位字节的方法是使用
mov[esi],al

printary
中,应使用
movzx-eax,字节ptr[esi]
将零扩展到eax
。(如果您想将数字视为
int8_t
而不是
uint8_t
,则可以使用movsx进行扩展签名)这样就避免了EAX的高24位需要归零


顺便说一句,你的代码有很多不必要的指令。e、 g

    MOV EAX,0                                       ; clearing registers, moving 0 into each, and initialize
毫无意义。如果您的第一次使用是只写的,那么在第一次使用寄存器之前不需要“init”或“declare”。您使用EDX所做的事情很有趣:

    MOV EDX,0                                       ; clearing registers, moving 0 into each, and initialize

    PUSH EDX                        ; preserves the original edx register value for future writeString call
    MOV EDX, OFFSET startArray  ; load EDX with address of variable
    CALL writeString                ; print string
    POP EDX                         ; return edx to previous stack
只有当您实际需要旧值时,才需要保存“Caller saved”寄存器。我更喜欢术语“保留通话”和“取消通话”。如果writeString破坏了它的输入寄存器,那么在函数返回后,EDX会保留一个未知值,但这没关系。无论如何,您不需要该值。(实际上,我认为Irvine32函数最多只能破坏EAX。)

在这种情况下,前一条指令仅将寄存器归零。整个街区可能是:

    MOV EDX, OFFSET startArray  ; load EDX with address of variable
    CALL writeString            ; print string
    xor  edx,edx                ; edx = 0
实际上,您也应该省略异或,因为您不需要将其归零。您没有将它用作循环中的计数器或任何东西,所有其他用途都是只写的


还要注意的是,带内存的
XCHG
有一个隐式
lock
前缀,因此它以原子方式执行读-修改-写操作(使其加载和存储速度比单独的
mov
指令慢得多)

您可以使用
movzx eax,word ptr[esi]
加载一对字节,并使用一个分支来决定是否使用
rol ax,8
交换它们。但是从字节存储转发到字加载的存储转发也不是很好


无论如何,这已经偏离了主题问题,这不是codereview.SE。

使用EAX绝对是可能的,事实上你已经做到了。你问“我想看看我是否能把AL转移到EAX,但那给了我一大堆错误。”想想这意味着什么。EAX是扩展AX寄存器,AL是AX的下分区。看看这个图表: . 如您所见,使用MOVZX指令将AL移动到EAX中只需将AL中的值放入EAX中,并从右向左填充零。将AL移动到AL中,并将EAX的其余部分设置为0。实际上,您可以将所有内容移动到EAX中,并以相同的方式运行程序,不会有任何区别,因为它使用的是相同的内存部分


还有,你为什么要这么频繁地推和弹出EAX?从运行时堆栈中推送/弹出内容的唯一原因是以后恢复它们,但您永远不会这样做,因此您可以让EAX中当时存在的内容消失。

显示您实际尝试的代码以及错误。确保在指令集引用中进行交叉检查,以查看您尝试执行的操作是否有效。注意,DWORD的大小为4字节,在某些地方,您将大小硬编码为
1
,而不是使用
TYPE
运算符。这不是一个很好的图表。
AX
标签位于其标记的低位16之外,而AL和AH位于其标记的寄存器内。这可能会让人误以为AX是EAX的高半部,而不是低半部。有关ASCII艺术图表,请参阅。和。这些都是链接的,所以你可以很快找到它们。顺便说一句,没有,即使使用
movzx