『壹』 如何編寫最簡單的匯編語言
了解計算機CPU原理:詳情請參照「80X86計算機組織」和「80X86的指令系統和定址方式」
求表達式Y=A*X+B-C的值,已知A、B、C分別存放在DA-1、DA-2、DA-3位元組單元,它們的值分別是:5 、 6、 7,X存放在INPUT位元組單元,結果Y放入JSJ_10位元組單元。
分析順序結構程序代碼:由記事本敲出來的
data segment da_1 db 5 da_2 db 6 da_3 db 7 input db 1 jsj_10 db 0data ends ;這一段在內存中定義了一個段,叫做data,並且其中存入了5個變數並且付入初值,db代表每個變數佔用1個位元組,若是dd則為字,為2個位元組code segment ;名字叫做code的段的定義,顯然這兒作為代碼段,當然code這個名字可以更改 assume cs:code,ds:data ;指定data為DS數據段,code為CS代碼段start: mov ax,data ;加法指令 mov ds,ax ;加法指令 mov al,da_1 ;加法指令
mov bl,input ;加法指令
mul bl ;乘法 add al,da_2 sub al,da_3 ;減法 mov jsj_10,al
exit: mov ah,4ch int 21h ;這兩行相當於ret(返回值),就像C語言中的return 0;
code ends end start
注釋: XXXX segment
.............
XXXX ends ;定義一個段
assume ds:XXXX 把XXXX段指定為ds(ds是段地址寄存器)
請先提前把masm edit debug link文件放入預定的文件夾,並把編寫的xxxx.asm代碼文件放入該文件夾,asm文件可用記事本寫成,並改格式txt為asm(有的看不到文件後綴.txt的請參照網路)
『貳』 匯編語言程序設計的一般步驟是什麼
匯編語言程序設計的基本步驟 了解了匯編語言指令的功能和用法,了解了匯編語言程序的編寫格式,就可以編制完整的匯編語言程序了。一個程序通常具有順序、分支、循環和子程序4種結構形式。順序程序結構就是指完全按順序逐條執行的指令序列。在程序設計過程中,順序結構大量存在,屢見不鮮。但一個完整的程序只是逐條去執行指令,這非常少見。常見的程序結構,是上述4種結構的混合體。一般來說,編制一個匯編語言程序的步驟如下:(1) 分析題意,確定演算法或演算法思想。演算法是指解決問題的方法和步驟。比如現有的一些計算方法和日常生活中解決問題的邏輯思維推理方法等。(2) 根據演算法畫出流程圖,簡單的情況也可不畫。畫出描述演算法的流程圖,可以首先從圖上檢驗演算法的正確性,減少出錯的可能,使得動手編寫程序時的思路更加清晰。(3) 分配存儲空間和工作單元,合理地使用寄存器。分配存儲空間和工作單元,是指存儲空間的分段和數據定義。另外,由於寄存器的數量有限,編寫程序時經常會感到寄存器不夠用。因此,對於位元組數據,要盡量使用8位寄存器。而採用適當的定址方式,也會達到節省寄存器的目的。(4) 根據流程圖編寫程序。這是編制匯編語言程序最為重要的一步。演算法里規定的功能,是要通過一條條指令描述出來的。為了提高編程能力,對於初學者,一是要多閱讀現有的程序,以學習別人的編程經驗;而更為重要的是,必須多親自動手編寫,不要怕失敗,只有通過無數次失敗,才能從中積累自己的編程經驗。(5) 上機調試運行程序。通過匯編的源程序,只能說明它裡面不存在語法錯誤。但是它是否能達到演算法所要求的預期效果,還必須經過上機調試,用一些實驗數據來測試,才能夠真正地得出結論。可以這么說,即使是一個非常有經驗的程序員,也沒有百分之百的把握說他編寫的程序一次就成功。 用流程圖表示演算法 流程圖用一些圖形框來代表各種操作。用圖形表示演算法,直觀形象,可以用來幫助人們對演算法的理解。下圖給出了一些常用的流程圖符號。
上圖中的判斷框(菱形)用來對一個給定的條件作出判斷,以決定如何執行其後的操作。它有一個入口,兩個出口,如下圖(a)所示。
連接點(圓圈)是用來將畫在不同地方的流程線連接起來。例如在下圖(b)里,有兩個圈裡寫著數字1的圓圈,它表示是從左邊的1出來,進到右邊圖的1里(這由流程線的方向給出)。可以看出,這兩個點其實就是同一個點,只是由於畫不下而分開來畫的。用連接點,可以避免流程圖中的流程線相互交叉或過長,從而使流程圖清晰。
注釋框不是流程圖中必需的部分。在流程圖中使用它,是為了對流程圖中的某些框的操作做一些必要的說明,以便使人們能夠更好地通過流程圖來理解演算法。
處理框反映做些什麼樣的操作,如把某個單元的內容送入某個寄存器,從某個存儲單元取出數據等。它是流程圖里最為本質的、出現最多的圖形框。
輸入/輸出框反映程序的輸入和輸出情況。計算機程序無外乎接收數據,進行處理,然後加以輸出,所以輸入/輸出框是必不可少的。
『叄』 編寫完整的匯編程序,判斷字類型變數X的值(用xxxx表示)是偶數還是奇數。若是偶數,將位元組類型變數
可以使用以下匯編程序來實現這個需求:
; 判斷字類型變數 X 是偶數還是奇數
; 如果是偶數,將位元組類型變數 BUF 置為 0
; 否則置為 1
; 定義變數 X 和 BUF
X: dw xxxx
BUF: db 0
; 開始執行程序
main:
; 將 X 寄存器中
mov ax, [X]
; 將 X 取模 2
div word ptr 2
; 判斷余數是否為 0
cmp ah, 0
; 如果余數為 0,說明是偶數,將 BUF 置為 0
jz even
; 否則,說明是奇數,將 BUF 置為 1
mov byte ptr [BUF], 1
; 跳轉到結束位置
jmp end
even:
; 將 BUF 置為 0
mov byte ptr [BUF], 0
end:
; 程序結束
ret
在上面的程序中,我們使用了 DIV 指令來將 X 取模 2,並使用 AH 寄存器來保存余數。如果余數為 0,說明 X 是偶數;如果余數不為 0,說明 X是奇數。
在上面的程序中,我們使用了 CMP 指令來比較 AH 寄存器的值是否為 0,如果是,就跳轉到 even 標簽處;否則,就跳轉到 end 標簽處。
在 even 標簽處,我們使用了 MOV 指令來將 BUF 置為 0。在 end 標簽處,我們使用了 RET 指令來結束程序。
這樣,我們就編寫了一個匯編程序,用來判斷字類型變數 X 是偶數還是奇數,並將位元組類型變數 BUF 置為 0 或 1。
『肆』 如何使用dosbox運行匯編語言程序
①安裝好dosbox,然後找到「dosbox...options.bat」,雙擊它,(別急著點dosbox.exe)。
然後就可以看到輸出的字元串
hello, world! @author: XXX
『伍』 mac book pro下如何編譯和運行匯編程序
匯編程序由定義好的段構成,每個段都有不同的目的,三個最常用的段:
1)data 段
匯編程序data(數據)段是可選的。
數據段聲明帶有初始值的數據元素,這些數據元素用作匯編程序的變數。
2)bss 段
匯編程序bss段 是可選的。
bss段聲明使用零(或 NULL)值初始化的數據元素。這些元素最常用作匯編程序中的緩沖區
3)text 段
匯編程序必須有 text(文本)段。
這個段是 在可執行程序內聲明指令碼 的地方。
定義段:
GNU匯編器使用 .section 命令語句聲明段。
.section 語句只使用一個參數------它聲明的段的類型
『陸』 這個匯編程序怎麼編啊
很簡單你編個循環然後用mov就可以了!
『柒』 如何用匯編編寫以下程序
一個匯編程序是由多個段組成的,這些段被用來存放代碼、數據或當作棧空間來使用。
一個有意義的匯編程序中至少要有一個段,這個段用來存放代碼。
程序結束標記
End 是一個匯編程序的結束標記,編譯器在編譯匯編程序的過程中,如果碰到了偽指令 end,就結束對源程序的編譯。
如果程序寫完了,要在結尾處加上偽指令end 。否則,編譯器在編譯程序時,無法知道程序在何處結束。
『捌』 如何編寫一個匯編程序,要求「從鍵盤接收一個四位的16進制數,並在終端上顯示與它等值的二進制數」
試編寫一段程序,要求對鍵盤輸入的小寫字母用大寫字母顯示出來。
『玖』 怎樣進入編寫匯編程序
以windows XP為例:
「開始」
——>「運行」
——>鍵入「cmd」,敲回車,此時便進入了命令提示符
——>在游標處鍵入「edit」,此時便進入了編輯界面,在這個界面輸入匯編語言源程序的代碼就行了,編輯完成後記得要保存。
『拾』 用匯編語言編寫一個小程序(比如hello,word!)請懂的人幫忙提供源碼
您正在看的匯編語言是:hello,world!win32匯編小程序。
首先我們看一個「復雜」的Win32匯編程序
程序用來顯示一個消息框
--------------------------------------------------
;文件名:3.asm
.386
.model flat ,stdcall
NULL equ 0
MB_OK equ 0
ExitProcess PROTO :Dword
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:Dword
includelib kernel32.lib
includelib user32.lib
.data
szText db "Hello, world!",0
szCaption db "Win32Asm",0
.code
start:
push MB_OK
lea eax,szCaption
push eax
lea eax,szText
push eax
push NULL
call messageboxa
xor eax,eax
push eax
call exitprocess
end start
--------------------------------------------------
編譯鏈接:
分下面兩步進行:
ml /c /coff 3.asm
link /subsystem:Windows /libpath:d:\masm7\lib 3.obj
第一步編譯生成3.obj文件
/c 表示只編譯,不鏈接
/coff 表示生成COFF格式的目標文件
第二步鏈接生成3.exe文件
/subsystem:windows 表示生成Windows文件
/libpath:d:\masm7\lib 表示引入庫的路徑為:d:\masm7\lib。
在安裝Masm32後,引入庫位於Masm32\Lib目錄下。
也可設置環境變數Lib的值:在dos提示符下鍵入Set Lib=d:\masm7\lib,這樣「鏈接」就可簡單寫成:
link /subsystem:Windows 3.obj,試想一下,在程序調試過程中,修改源程序是常用的事啦,每次編譯鏈接都要帶/libpath:...那該有多煩人呢。當然,我們也可在源程序中直接給出引入庫的位置,這樣,鏈接時就方便啦,如下:
includelib d:\masm7\lib\kernel32.lib
includelib d:\masm7\lib\user32.lib
--------------------------------------------------
執行:在dos提示符下鍵入3,回車,出現一個消息框,哈哈,真正的Win32程序!
--------------------------------------------------
深入分析:
看一下源程序,有這么兩行:call messageboxa\call exitprocess。大家一看都知道,這是子程序調用,但是我們並沒寫這樣的子程序,事實上,這些是API函數。作為函數,我們在調用時可能需要傳送給函數一些參數,程序怎麼知道傳送的參數有哪些,類型是什麼呢?就是通過函數原型定義,如下所示:
ExitProcess PROTO :Dword
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:Dword
可以看出,ExitProcess有一個參數,MessageBoxA有四個參數,這些參數都是Dword類型。
在Win32中,參數的傳遞都是通過堆棧來完成的。象MessageBoxA這個函數有四個參數,究竟是左邊的先壓入堆棧還是右邊的先入棧呢?.model flat,stdcall給出了答案。stdcall 指定參數是從右到左壓入堆棧的,且調整堆棧是在子程序返回時完成的。在源程序中不需要用「add sp,值」來保持堆棧平衡。對MessageBox,在API手冊中是這樣定義的:
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType &n
您正在看的匯編語言是:hello,world!win32匯編小程序。
bsp; // style of message box
)
;所以會有我們的程序段:
push MB_OK
lea eax,szCaption
push eax
lea eax,szText
push eax
push NULL
call messageboxa
看看上面的程序,不難想到,假如在寫程序時,少往堆棧里壓入一個數據,那將是一個致命的錯誤。能不能將這種檢查參數個數是否匹配的工作交給計算機來完成呢?這是可以的,INVOKE指令可以幫助我們完成這樣的工作。假如你的參數個數不正確,連接器將給出錯誤提示。所以,極力建議你使用invoke代替call來調用子程序,當然,這不是絕對的。使用invoke上面的指令就可簡寫成下面的樣子,看起來簡煉多啦,查錯也方便啦!
invoke messageboxa, NULL,addr szText,addr szCaption,MB_OK
另外,像NULL,MB_OK都是一些常量,這樣的常量有很多,還有很多的結構,如果在我們的程序中一開始都寫這么多的東西,可能一下子就把你嚇怕啦,也容易出錯,更不便於看程序的主要部分。hutch整理的Windows.inc包含了WIN32編程所需要的常量和結構體的定義,我們可簡單的用一個include指令將這些常量和結構的定義插入到我們的文件中:
include d:\masm32\include\Windows.inc
但是Windows.inc中並不包含函數原型的聲明,還要從其他的頭文件中得到函數原型的聲明,比如:messageboxa的原型聲明在user32.inc文件中,exitprocess在kernel32.inc文件中。這些頭文件都放在 \masm32\include文件夾下。
還有,要用Windows.inc,必須使用option casemap:none,它的意思是告訴 MASM 要區分符號的大小寫,譬如:start和START是不一樣的。否則,一個小小的程序,可能會出成百上千的錯誤呀!
其他的,就不再細說啦,到此,上面的程序可重新修改如下:
-----------------------------------------------------------------
;最終的結果
.386 ;表示要用到386指令
.model flat,stdcall ;32位程序,要用flat啦!;stadcall,標准調用
option casemap:none ;區別大小寫
include Windows.inc ;包括常量及結構定義
include kernel32.inc ;函數原型聲明
include user32.inc
includelib kernel32.lib ;用到的引入庫
includelib user32.lib
.data;數據區,定義2個字元串
szText db "Hello, world!",0
szCaption db "Win32Asm",0
.code ;代碼開始執行處
start:
invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
;調用MessageBoxAPI函數
invoke ExitProcess,NULL ;程序退出
end start;結束
------------------------------------
編譯鏈接:
ml /c /coff /I d:\masm7\include 3.asm ;注意開關符識別大小寫
link /subsystem:Windows /libpath:d:\masm7\lib 3.obj
/I d:\masm7\include 表示*.inc文件的位置,也可設置環境變數Set include=d:\masm7\include來簡化操作,也可在程序中明確指出*.inc的位置。
前面講的都是用兩條指令來完成編譯鏈接,實際上用一條指令也可完成,如下:
ml /coff /I d:\masm7\include 3.asm /link /subsystem:Windows /libpath:lib
若*.inc及引入庫在源程序中都明確指出其位置,則可簡化為:
ml /coff 3.asm /link /subsystem: