我有以下程序,可以从 A 打印到 Z,中间有一个空格。在下面的程序中,我理解了其余的代码,但不明白为什么使用PUSH DX和指令。POP DX如果我运行代码而不使用PUSH DXand POP DX,它只会打印“!” 而不是角色。
.model small
.stack
.data
VAL DB 'A'
.code
MAIN PROC
SPACE MACRO
MOV DL, ' '
MOV AH, 02h;
INT 21H
ENDM
MOV AX, @DATA
MOV DS, AX
MOV CL, 26
MOV DL, 65 ; MOV DL, VAL
PRINT:
MOV AH, 02H
INT 21H
PUSH DX
SPACE
POP DX
INC DL
DEC CL
JNZ PRINT
MOV AH, 4CH
INT 21H
MAIN ENDP
END …Run Code Online (Sandbox Code Playgroud) 据我了解,8086处理器有4个内存段:堆栈段、代码段、数据段和额外段,以及相应的段寄存器(SS, CS, DS, ES)
问题是:“为什么?”
为什么不将数据段和代码段结合起来?
为什么我们需要额外的段?
为什么是4?
我知道这个问题可能听起来很无聊,但我在去年在我的大学进行的一次“微处理器架构”考试中发现了这个问题。
提前致谢。
我有一个指向整数数组开头的整数指针,并且我正在尝试交换程序集 x86 中的两个值。这是我的代码:
movq (%rdi,%rcx,4),%r8 # SWAP
movq 4(%rdi,%rcx,4),%r9
movq %r9,(%rdi,%rcx,4)
movq %r8,4(%rdi,%rcx,4)
Run Code Online (Sandbox Code Playgroud)
rdi包含指针,并且两个值的地址计算是正确的(rcx第一次迭代中只是 0),但是,这是我进行交换时发生的情况:
(gdb) x/5wd $rdi
0x602010: 31 1 2 3
0x602020: 0
(gdb) x/5wd $rdi
0x602010: 1 2 2 3
0x602020: 0
(gdb) x/5wd $rdi
0x602010: 1 31 2 3
0x602020: 0
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,第三个值被第一个和第二个值的交换所替换,我不明白为什么。关于我应该在哪里寻找错误的任何建议?
Intel x86 汇编中执行以下操作的最有效方法是什么(a,b是 32 位浮点数):
从xmm1: [-, -, a, b]到xmm1: [a, a, b, b]
我找不到任何有用的说明。
我的想法是将a和b复制到其他寄存器,然后将xmm1寄存器移动 4 个字节并将a或b移动到最低的 4 个字节。
在这篇关于寄存器保存的维基百科文章中,我读到调用者函数负责某些寄存器(以防止其先前的数据被更改),而被调用者则负责其他寄存器。
我的问题是为什么我们必须让事情复杂化?为什么不让所有寄存器成为调用者的责任,在调用函数之前备份现有值并在之后重新加载它们?
我没有看到执行这些步骤有任何性能提升,有人可以帮助我理解吗?
我正在阅读汇编代码优化手册第 2.3 节常见编码陷阱 - 第 9 页
无与伦比的 PUSH 和 POP 指令。对于通过函数的所有可能路径,PUSH 和 POP 指令的数量必须相等。例子:
Run Code Online (Sandbox Code Playgroud)push ebx test ecx, ecx jz Finished ... pop ebx Finished: ; Wrong! Label should be before pop ebx ret这里,如果 ECX 为零,则不会再次弹出推送的 EBX 值。结果是RET指令会弹出EBX之前的值并跳转到错误的地址。
我的疑问是:jz指令不是将返回地址存储在堆栈中吗?什么其他指令一样jmp,jg,jge,jl,jle等?
从头开始编程的挑战之一是“修改程序以使用结束地址而不是数字 0 来知道何时停止。”
\n我发现很难做到这一点,因为到目前为止,这本书只介绍了movl,,cmpl(incl以及寻址模式)和jmp指令。基本上,下面的代码片段中的所有内容都是到目前为止所介绍的。我发现的所有解决方案都涉及本书中尚未介绍的说明。下面的代码查找集合中的最大值。
.section .data\ndata_items: #These are the data items\n.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0\n\n.section .text\n.globl _start\n_start:\n movl $0, %edi # move 0 into the index register\n movl data_items(,%edi,4), %eax # load the first byte of data\n movl %eax, %ebx # since this is the first item, %eax is\n # the biggest\nstart_loop: # start loop\n cmpl $0, %eax # check to see if we\xe2\x80\x99ve hit the end\n je loop_exit\n incl %edi # …Run Code Online (Sandbox Code Playgroud) 我想计算数组中 1 的数量(使用 MASM32)。在第一次迭代中,我在EAX. 我得到的不是 00000000,而是 00010000。因此,计数器中的值也不正确ECX。
.386
.model small
.data
var1 dw 0,1,1
.code
main PROC
LEA ESI, var1
MOV EBX, 3
MOV ECX, 0
L1:CMP EBX, 0
JE L3
MOV EAX, [ESI]
CMP EAX, 0
JE L2
INC ECX
L2:DEC EBX
ADD ESI, 2
JMP L1
L3:INVOKE ExitProcess, 0
main ENDP
END main
Run Code Online (Sandbox Code Playgroud)
看这个图片,得到 00010000EAX而不是 00000000 因为内容在[ESI] 开始时是 0

所以我正在阅读 SYSTEM V AMD64 ABI,其中写道我们必须使用向量寄存器来保存 stdargs 并设置AL为用于放置参数的寄存器的数量。
为什么需要使用向量寄存器?我们不能将它们放入堆栈并将AL寄存器设置为堆栈中的参数数量吗?
我用汇编语言为 avr atmega328P 编写了这段代码。它使用按钮打开和关闭 LED,但在 proteus 中我收到此错误:
PC=0x002A 处的无效操作码 0xFFFF
这是我的代码:
.INCLUDE "M328Pdef.inc"
ldi r16,HIGH(RAMEND)
out SPH, R16
ldi r16,LOW(RAMEND)
out SPL, R16
start:
ldi r16,0xFF
out DDRB,r16
ldi r17,0x00
out DDRD,r17
ldi r21,0x00
ldi r23,0x01
Forever:
in r20,PIND
cp r20,r21
BREQ ledon
cp r20,r23
BREQ ledoff
rjmp Forever
ledon:
ldi r22,0x01
out PORTB,r22
ret
ledoff:
ldi r24,0x00
out PORTB,r24
ret
Run Code Online (Sandbox Code Playgroud)
有人有解决办法吗?