我在写装配还是NASM?

cam*_*cam 3 assembly nasm

我厌倦了这个.我一直试图抓住装配一段时间,但我觉得我正在编写我的编译器而不是语言.

我一直在使用这个教程,到目前为止它给了我地狱.我正在使用NASM,这可能是问题,但我认为它是最受欢迎的.我只是想学习最一般的汇编形式,所以我决定学习x86.我一直遇到愚蠢的错误,比如无法增加变量.这是最新的一个:无法使用div.

mov bx, 0;
mov cx, 0;
jmp start;
 start:
 inc cx;
 mov ax, cx;
 div 3; <-- invalid combination of opcode and operand
 cmp ah,0;
 jz totalvalue;
 mov ax, cx;
 div 5; <-- invalid combination of opcode and operand
 cmp ah, 0;
 jz totalvalue;
 cmp cx, 1000;
 jz end;

 totalvalue:
 add bx,cx;
 jmp start;

jmp end;
 end:
   mov ah,4ch;
   mov al,00;
   int 21h;
Run Code Online (Sandbox Code Playgroud)

我应该更改编译器吗?看起来分工应该是标准的.我是否需要阅读两个教程(一个在NASM上,一个在x86上?).有关这个问题的任何具体帮助?

dan*_*ben 8

可以这样想:x86架构真的只能理解机器代码.像NASM这样的汇编程序将从汇编代码转换为机器代码.所以你选择汇编程序并不重要,只要它做正确的翻译(NASM就是这样).

这类似于是否使用javacEclipse或内置编译器的问题.他们都将编译有效的Java.我知道汇编程序也支持一些额外的宏和类似的东西,但这似乎并不适用于这种情况.

此外,NASM站点本身只是指向x86汇编的英特尔文档,因此您可以确定它不会期望它的某些特殊形式.

现在,我确实发现这个站点记录了DIV指令,它有这样的说法:

80x86除法指令执行64/32除法(仅限80386及以后),32/16除法或16/8除法.这些说明采用以下形式:

            div     reg     For unsigned division
            div     mem

            idiv    reg     For signed division
            idiv    mem

            aad             ASCII adjust for division
Run Code Online (Sandbox Code Playgroud)

这样可以解释你的错误.参数div可以是寄存器或内存位置,但是你给它一个常量.

  • 我想补充一点,div操作码不接受立即值(这是他们所谓的,而不是"常量").如果您正在查看操作码引用,则立即操作数由缩写"imm"引用,有时后跟大小如32位的"imm32",16位的"imm16"等,依此类推.有几个操作码有这样的奇怪要求,但div是最烦人的.虽然可能比您需要的更详细,但http://ref.x86asm.net/coder32.html将为您提供所有说明和可能的操作员组合. (3认同)

Har*_*lby 6

与任何其他语言一样,汇编的一个原因是它部分地由汇编程序定义.那个"div 5"对我来说似乎很奇怪 - 但是我学会了使用MASM的汇编,它有不同的语法.基于本教程中的注释,看起来用于该教程的汇编程序对指令有一些"隐含的"操作数,而NASM则没有,并且期望div指令的Intel语法.

恕我直言,你最好通过使用NASM,但获得一个NASM特定的教程,或者面向'纯'英特尔语法的教程.该大会的艺术本书是为Intel语法一个很好的资源.


pax*_*blo 6

英特尔不支持立即参数div(仅限寄存器和内存参数),因此您使用的任何教程都是为非标准汇编程序构建的.