VS2015中运行32位汇编程序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sxhelijian/article/details/74853459

【前言】
  这学期开汇编语言课。作为培养方案中的一门选修课,与课组中教微机原理、嵌入式的同事商量,决定这门课就以8086为载体,带大家入门即可。不过,在课程结束之前,也向同学们做了拓展。
  本文的版权属于我的2015级学生小鲁同学。他在课程设计阶段,费了不少周折,配置环境,完成了32位汇编程序的开发。他将整个过程做了记录,并且完成本文。
  我说:“你将这些文字发成博客做个分享。”他说:“不发了。老师,您的博客点击量大,给您吧。”
  这是本文的由来。感谢这位自主、慷慨的弟子!

【正文】
  Visual Studio 2015只需要14步就可以运行32位汇编语言。你必须创建一个32位的控制台应用(原本32位控制台应用用于C++编写)并且修改几个地方的设置。
Step1:选择左上角的创建项目,选择创建Win32控制台应用程序。(Depending on your Visual Studio configuration, you might have to find Visual C++ under the “Other Languages” category in the left panel.)当然你的Visual Studio 2015的win32控制选项可能需要你自己找找了,但是Visual Studio 2015必须可以编写并运行C++程序。
这里写图片描述

这里写图片描述
Step2:都搞好之后点确定,进行下一步的选择,点击下一步,之后选择空项目。
这里写图片描述

这里写图片描述
Step3:点完成保存项目的设置。
Step4:此时方案已经生成,在右边显示了当前的项目名称,接下来需要点击鼠标右键选择生成依赖项,选择生成自定义,此时会出现一个生成自定义文件的选择对话框,选择masm,然后点击确定。
这里写图片描述

这里写图片描述
Step5:此时就可以进行基本的80386汇编程序了,在右上方的项目的源文件中添加新建项,创建C++文件,将名称改为*.asm作为汇编程序,之后点击添加。添加一个测试文件试试是否可行。

; AddTwo.asm - adds two 32-bit integers.
; Chapter 3 example

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

.code
main proc
    mov eax,5               
    add eax,6               

    invoke ExitProcess,0
main endp
end main

将此段汇编程序写入创建好的mytest.asm文件中,点击上方的生成,生成解决方案,之后观察当前控制台的提示,成功之后就可以点击本地Windows调试器运行了。
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

Step6:既然是Intel汇编,那么想使用Irvine32头文件中的给出的函数,就需要再加一些配置了,首先需要下载这个文件,下面给出这个安装包的下载地址:http://www.kipirvine.com/asm/examples/Irvine_7th_Edition.msi
下载好之后安装即可,我安装在C盘的默认目录下,即:C:\Irvine。之后进行配置。
Step7:右击项目,选择属性,在弹出的对话框中选择Microsoft Macro Assembly,就会看到如下配置。
这里写图片描述

这里写图片描述

Step8:选择General,然后点击Include Paths,点击编辑,将刚刚安装的Irvine的目录写入编辑框中,This tells the assembler where to find files having a filename extension of “.inc”.告诉编辑器去哪里寻找后缀名位inc的文件,输入好点击确定。
这里写图片描述

这里写图片描述
Step9:接下来我们想让VS2015生成链接文件,方便我们查看汇编代码对应的机器代码,点击Listing File,点击Assembled Code Listing File点击编辑,输入$(ProjectName).lst,确定。
这里写图片描述
Step10: 找到连接器,选择输入,在附加依赖库中添加irvine32.lib,注意每个依赖库以分号结尾
这里写图片描述
Step11:选择连接器的常规,选择附加库目录,将安装的地址写入,使得连接器可以找到Irvine32.lib这个库文件,之后点击确定。
这里写图片描述

这里写图片描述

这里写图片描述
Step12:选择连接器的调试,将生成调试信息选择为“优化以便于调试(/DEBUG)”
这里写图片描述
Step13:选择连接器的高级,选择映像具有安全异常处理程序,选择否。
这里写图片描述
Step 14:Ok,配置完成,试试调用Irvine32头文件是否可行。下面给出一个在Github上托管的代码的实例:

TITLE Programming Assignment #1    (Project01.asm)

; Author:                                   Andrew Pierno
;
; Description: Write and test a MASM program to perform the following tasks:
;   1. Display your name and program title on the output screen.
;   2. Display instructions for the user.
;   3. Prompt the user to enter two numbers.
;   4. Calculate the sum, difference, product, (integer) quotient and remainder of the numbers.
;   5. Display a terminating message.
;   EC: Validate second number is less than the first
;   EC: Loop until user decides to quit
;   EC: Calculates and displays division as floating point number rounded to .001

INCLUDE Irvine32.inc

.data
myName              BYTE    "Andrew Pierno ", 0
programTitle        BYTE    "Programming Assignment #1", 0
instructions        BYTE    "Please enter two numbers, and I'll show you the sum, difference, product, quotient, and remainder.", 0
prompt_1            BYTE    "First Number: ", 0
prompt_2            BYTE    "Second Number: ", 0
firstNumber         DWORD   ?                            ; integer entered by user
secondNumber        DWORD   ?                            ; second integer entered by user.
goodBye             BYTE    "Goodbye",0
equalsString        BYTE    " = ", 0
sum                 DWORD   ?
sumString           BYTE    " + ",0
difference          DWORD   ?
differenceString    BYTE    " - ",0
product             DWORD   ?
productString       BYTE    " * ",0
quotient            DWORD   ?
quotientString      BYTE    " / ",0
remainder           DWORD   ?
remainderString     BYTE    " remainder ",0

; Extra Credit
EC1prompt           BYTE    "**EC: This program verifies the second number is less than the first", 0
EC1warn             BYTE    "The second number must be less than the first!", 0
EC2prompt           BYTE    "**EC: This program also calculates and displays the quotient as a floating-point number, rounded to the nearest .001", 0
EC2string           BYTE    "EC: Floating-point value: ", 0
EC2FloatingPoint    REAL4   ?   ; short real single precision floating point variable
oneThousand         DWORD   1000                        ; to convert an int to a floating point number rounded to .001 (can be changed to increase or decrease precision)
bigInt              DWORD   0                           ; represents the floating point number multiplied by 1000
ECremainder         DWORD   ?                           ; for floating point creation
dot                 BYTE    ".",0                       ; to serve as the decimal place of a floating point number
firstPart           DWORD   ?                           ; for the first part of the floating point representation of the quotient
secondPart          DWORD   ?                           ; fot the part of the floating point number after the decimal place
temp                DWORD   ?                           ; temporary holder for floating point creation
EC3prompt           BYTE    "EC: Would you like to play again? Enter 1 for YES or 0 for NO: ", 0
EC3explain          BYTE    "**EC: This program loops until the user decides to quit.", 0
EC3response         DWORD   ?                           ; BOOL for user to loop or exit.

.code
 main PROC

    ; Introduction
    ; This section prints out the instructions and extra credit options

        mov     edx, OFFSET myName
        call    WriteString
        mov     edx, OFFSET programTitle
        call    WriteString
        call    CrLf
        mov     edx, OFFSET EC1prompt
        call    WriteString
        call    CrLf
        mov     edx, OFFSET EC2prompt
        call    WriteString
        call    CrLf
        mov     edx, OFFSET EC3explain
        call    WriteString
        call    CrLf

    ; Get The Data
    ; This section gets the first and second number and jumps if the user's second number is greater than the first number
    ; the program will still allow them to loop even if they enter a second number that is greater than the first.
        mov     edx, OFFSET instructions
        call    WriteString
        call    CrLf

            ; get firstNumber
top:
            mov     edx, OFFSET prompt_1
            call    WriteString
            call    ReadInt
            mov     firstNumber, eax


            ; get secondNumber
            mov     edx, OFFSET prompt_2
            call    WriteString
            call    ReadInt
            mov     secondNumber, eax

            ; **EC: Jump if second number greater than first
            mov     eax, secondNumber
            cmp     eax, firstNumber
            jg      Warning
            jle     Calculate

Warning:
            mov     edx, OFFSET EC1warn
            call    WriteString
            call    CrLf
            jg      JumpToLoop              ; jump if secondNumber > firstNumber


Calculate:      ; Calculate Required Values
                ; sum
                mov     eax, firstNumber
                add     eax, secondNumber
                mov     sum, eax

                ; difference
                mov     eax, firstNumber
                sub     eax, secondNumber
                mov     difference, eax

                ; product
                mov     eax, firstNumber
                mov     ebx, secondNumber
                mul     ebx
                mov     product, eax


                ; quotient
                mov     edx, 0
                mov     eax, firstNumber
                cdq
                mov     ebx, secondNumber
                cdq
                div     ebx
                mov     quotient, eax
                mov     remainder, edx

                ; EC floating point representation of quotient and remainder
                fld     firstNumber                 ; load firstNumber (integer) into ST(0)
                fdiv    secondNumber                ; divide firstNumber by secondNumber ?
                fimul   oneThousand
                frndint 
                fist    bigInt
                fst     EC2FloatingPoint            ; take value off stack, put it in EC2FloatingPoint

            ; Display Results

                ; sum results
                mov     eax, firstNumber
                call    WriteDec
                mov     edx, OFFSET sumString
                call    WriteString
                mov     eax, secondNumber
                call    WriteDec
                mov     edx, OFFSET equalsString
                call    WriteString
                mov     eax, sum
                call    WriteDec
                call    CrLf

                ; difference results
                mov     eax, firstNumber
                call    WriteDec
                mov     edx, OFFSET differenceString
                call    WriteString
                mov     eax, secondNumber
                call    WriteDec
                mov     edx, OFFSET equalsString
                call    WriteString
                mov     eax, difference
                call    WriteDec
                call    CrLf

                ; product results
                mov     eax, firstNumber
                call    WriteDec
                mov     edx, OFFSET productString
                call    WriteString
                mov     eax, secondNumber
                call    WriteDec
                mov     edx, OFFSET equalsString
                call    WriteString
                mov     eax, product
                call    WriteDec
                call    CrLf

                ; quotient results
                mov     eax, firstNumber
                call    WriteDec
                mov     edx, OFFSET quotientString
                call    WriteString
                mov     eax, secondNumber
                call    WriteDec
                mov     edx, OFFSET equalsString
                call    WriteString
                mov     eax, quotient
                call    WriteDec
                mov     edx, OFFSET remainderString
                call    WriteString
                mov     eax, remainder
                call    WriteDec
                call    CrLf

                ; EC2 Output
                mov     edx, OFFSET EC2string
                call    WriteString
                mov     edx, 0
                mov     eax, bigInt
                cdq
                mov     ebx, 1000
                cdq
                div     ebx
                mov     firstPart, eax
                mov     ECremainder, edx
                mov     eax, firstPart
                call    WriteDec
                mov     edx, OFFSET dot
                call    WriteString

                ;calculate remainder
                mov     eax, firstPart
                mul     oneThousand
                mov     temp, eax
                mov     eax, bigInt
                sub     eax, temp
                mov     secondPart, eax
                call    WriteDec
                call    CrLf

        ; Loop until user quits
        ; prompts the user to enter a 0 or 1 to continue looping.
        ; if they do want to play again, it takes them to section 'top'
        ; skipping the instrucitons

                ; get response for loop

JumpToLoop:         mov     edx, OFFSET EC3prompt
                    call    WriteString
                    call    ReadInt
                    mov     EC3response, eax
                    cmp     eax, 1
                    je      top             ; jump to top if response == 1


                ; Say Goodbye
                    mov     edx, OFFSET goodBye
                    call    WriteString
                    call    CrLf

    exit    ; exit to operating system
main ENDP

END main

以同样的方式生成解决方案,这个时候输出正确!可以进行愉快的32位汇编喽!
这里写图片描述
注意调试断点的使用!红点就是断点。
这里写图片描述
调试时调出内存管理,利用反汇编进行内存内容的查看,当然也可以把寄存器也调出来:
这里写图片描述

这里写图片描述
这个是个人调整之后的调试界面,左下角的寄存器部分也已进行多种选项,显示标志寄存器,左上角有个反汇编,
这里写图片描述

这里写图片描述

这里写图片描述
将里边的内存地址赋值,在内存查看部分可以看到内存的信息。
这里写图片描述

这里写图片描述
点击逐步运行,可以看到寄存器的变化,以及标志寄存器,红色代表改变。
这里写图片描述
程序编译成功之后生成的列表文件和编写的文件在同一目录下。
这里写图片描述
对列表文件的部分截屏:
这里写图片描述
最后还差一个变色包,让汇编环境关键字变色。
MASM syntax highlighting
When a text editor uses syntax highlighting, language keywords, strings, and other elements appear in different colors. Visual Studio highlights MASM reserved words and strings, as shown in the following example:
这里写图片描述
This won’t happen automatically, but you can create a syntax definition file named Usertype.dat that contains MASM keywords. Then when Visual Studio starts, it reads the syntax file and highlights MASM keywords.
There is an interesting third party Visual Studio 2015 extension named Asm-Dude, featuring a rich set of syntax highlighting and code completion features. You can download it from GitHub.
If you decide to use Visual Studio’s built-in MASM syntax highlighter, here are the required steps to set it up:
1) Download the Usertype.dat file (enclosed in a ZIP file) given here to a folder in which you have read/write permissions. If you are using Windows 7, download to My Documents, or C:\temp, or any folder that doesn’t have security restrictions.
2) Copy Usertype.dat to the C:\Program Files\Microsoft Visual Studio 12.x\Common7\IDE folder. In 64-bit windows, Program Files will be named Program Files(x86).
Windows will display a verification dialog before copying the file.
3) Open Visual Studio, select Options from the Tools menu, select Text Editor, and select File Extension. On the right side of the dialog (shown below), enter asm as the extension, select Microsoft Visual C++ from the Editor list, and click the Add button. Click the OK button to save your changes.
这里写图片描述
Close Visual Studio and restart it. Open your project and display an ASM file. You should see syntax highlighting in the editor. There is a glitch in the highlighting–assembly language comment line starts start with a semicolon, which C++ doesn’t recognize. But this is a simple workaround: add an extra // right after the semicolon, like this, which will cause the comments to appear in their usual green color。
或者给出VS2015变色安装包,不过安装完之后需要在VS2015中更新一下,重启才有效果。

展开阅读全文

没有更多推荐了,返回首页