Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.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
C 尝试在Visual Studio中运行程序集时出现问题_C_Visual Studio_Assembly_Visual Studio 2012 - Fatal编程技术网

C 尝试在Visual Studio中运行程序集时出现问题

C 尝试在Visual Studio中运行程序集时出现问题,c,visual-studio,assembly,visual-studio-2012,C,Visual Studio,Assembly,Visual Studio 2012,我试图在VisualStudio2012中运行一些汇编代码,并在C中调用它,仅用于测试目的。由于我没有编写汇编代码的经验,我不知道出了什么问题,所以我非常感谢您的帮助 我在编译代码时遇到以下错误: Error 5 error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\callee.obj" /W3 /errorReport:prompt /Tacallee.asm" exited

我试图在VisualStudio2012中运行一些汇编代码,并在C中调用它,仅用于测试目的。由于我没有编写汇编代码的经验,我不知道出了什么问题,所以我非常感谢您的帮助

我在编译代码时遇到以下错误:

Error   5   error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\callee.obj" /W3 /errorReport:prompt  /Tacallee.asm" exited with code 1. C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\BuildCustomizations\masm.targets 49  5   ProjetoASM
Error   2   error A2206: missing operator in expression C:\Users\Suporte\Desktop\ASM\ProjetoASM\ProjetoASM\callee.asm   18  1   ProjetoASM
Error   3   error A2206: missing operator in expression C:\Users\Suporte\Desktop\ASM\ProjetoASM\ProjetoASM\callee.asm   21  1   ProjetoASM
Error   4   error A2206: missing operator in expression C:\Users\Suporte\Desktop\ASM\ProjetoASM\ProjetoASM\callee.asm   8   1   ProjetoASM
Error   1   error A2022: instruction operands must be the same size C:\Users\Suporte\Desktop\ASM\ProjetoASM\ProjetoASM\callee.asm   15  1   ProjetoASM
和汇编代码:

PUBLIC hello_from_asm
EXTERN puts:PROC

.model flat

.data

    msg    db 'Hello, world!',0xa    
    len    equ $ - msg

.code

hello_from_asm PROC
        mov     edx,len                  
        mov     ecx,msg                         
        mov     ebx,1                            
        mov     eax,4                         
        int     0x80                          

        mov     eax,1                            
        int     0x80                              
hello_from_asm ENDP

END
这应该输出一个“你好,世界!”,所以任何其他可能有效的想法都是受欢迎的

C完整性代码:

#include <stdio.h>

extern void hello_from_asm();

int main(){
    printf("Hello from C");
    hello_from_asm();
    return 0;
}
#包括
extern void hello_from_asm();
int main(){
printf(“来自C的你好”);
你好,我是_asm();
返回0;
}

这些详细的MASM错误消息说明了一切

您需要使用MASM样式。上述指令尝试在32位寄存器中加载msg的第一个字节。这就是“大小不匹配”错误。
您需要的是在
ECX
中加载msg的地址。使用

mov ecx, offset msg
其他错误可能是无法识别
0x
十六进制前缀。尝试改用
h
十六进制后缀。(
0Ah
80h


以上内容很容易更改,您的代码将很好地组装。但是不要运行它,因为
int 80h
指令是一个Linux系统调用,在Visual Studio 2012(Windows)上不起作用。

打印“Hello World”的32位Visual Studio | Masm程序示例。我包括了最常见的指令。“legacy_stdio_definitions.lib”用于VS2015及更高版本,因为printf和scanf已更改为与C编译器的输出内联。VS2012可能不需要它

        .686p                   ;enable instructions
        .xmm                    ;enable instructions
        .model flat,c           ;use C naming convention (stdcall is default)

;       include C libraries
        includelib      msvcrtd
        includelib      oldnames
        includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...

        .data                   ;initialized data
pfstr   db      "Hello world!",0dh,0ah,0
        .data?                  ;uinitialized data
        .stack  4096            ;stack (optional, linker will default)

        .code                   ;code 
        extrn   printf:near
        public  main

main    proc

        push    offset pfstr    ; 32-bit mode uses stack args
        call    printf
        add     esp,4           ; cdecl is caller-pops

        xor     eax,eax         ; return 0
        ret
main    endp

        end

int 0x80
是32位Linux系统cal ABI。作为本机Windows程序的一部分,这永远不会起作用。您从一些NASM示例复制的部分仍然使用NASM语法,这似乎是MASM所抱怨的。e、 g.我认为MASM不允许
0xa
,只允许
0aH
用于十六进制数字文本。在MASM中,
mov-ecx,msg
表示
mov-ecx,[msg]
。这并不重要,因为在Windows下,
int0x80
只会出错,所以在ECX中是否有指针或4字节的ASCII数据并不重要。我认为重要的是,一旦你将其组装起来,它只会在
int80h
上出错,因为这是Windows,而不是Linux。和
mov ecx,msg
同样可以描述为试图加载
msg
的前4个字节(基于表示操作数大小的寄存器),这就是为什么MASM会抱怨操作数大小不匹配的原因,因为
symbol:db
还意味着引用该符号的操作数大小。
printf
永远不是stdcall;它需要可变数量的参数。您上次的更改使评论错误/误导。是
stdcall
也使用堆栈参数,但用于在32位模式下调用printf的调用约定是
cdecl
stdcall
不会在通话后使用
addesp,4
。@PeterCordes-我编辑了我的答案。我的困惑是由于64位模式调用约定,在这种情况下,printf的前两个参数在rcx和rdx中。我想可能会有一个32位的快速调用版本的printf,它可以在ecx和edx中使用它的前两个参数,尽管它可能会导致稍微慢一些的代码,因为在32位模式中没有那么多寄存器。哦,是的,不幸的是32位
fastcall
被调用,所以它不能用于printf。(ISO C要求printf忽略格式字符串没有告诉它的额外未使用的参数)。64位调用约定是调用方pops,因此它可以用于可变函数,并且可以传递RCX、RDX、R8、R9中的前4个参数(如果它们是整数/指针)。@PeterCordes-更令人困惑的是VS2015和更高版本现在在C/C++编译代码中内联printf和scanf(如果输出C/C++生成的汇编代码,您可以看到这一点)。幸运的是,至少通过VS2019,遗留库仍然存在。
        .686p                   ;enable instructions
        .xmm                    ;enable instructions
        .model flat,c           ;use C naming convention (stdcall is default)

;       include C libraries
        includelib      msvcrtd
        includelib      oldnames
        includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...

        .data                   ;initialized data
pfstr   db      "Hello world!",0dh,0ah,0
        .data?                  ;uinitialized data
        .stack  4096            ;stack (optional, linker will default)

        .code                   ;code 
        extrn   printf:near
        public  main

main    proc

        push    offset pfstr    ; 32-bit mode uses stack args
        call    printf
        add     esp,4           ; cdecl is caller-pops

        xor     eax,eax         ; return 0
        ret
main    endp

        end