c語言嵌入匯編
#pragma
asm
匯編代碼
#pragma
endasm
這是寫法
但是要完成這種寫法需要進行設置
首先看到你keil左邊那個工程列表
→
選中你嵌入了匯編的C文件
→
右鍵→選擇Option
for
file
然後看到彈出的對話框
在對話框右邊偏少
有5個復選框
初始的設置時
復選框前面全是灰色的勾
點擊「Generate
Assembler
SRC
File」和「Assemble
SRC
File」這兩個選項
直到勾變成黑色
保存即完成設置
『貳』 關於嵌入式C語言內嵌匯編的問題,求解答~100分奉上
參數:地址,長度,數據,實現的功能:快速復制。
匯編中的一些最基本的語句:
ADD 寄存器1,寄存器2,寄存器3;//三個寄存器中的值相加
MOV 寄存器1,寄存器2;//將寄存器2的值放到寄存器1中
LOOP:NOP;跳轉指令,一個時鍾周期,等於延時1個時鍾周期
CMP 寄存器1,寄存器2;//兩寄存器中的值進行比較,這個比較結果(0或1)我給你忘了,你可以查查
……
下面幾個不記得了,你好好查查吧!就是匯編中的最基本的操作指令,最終實現就是快速復制的操作!不必採納,只是為了幫助你一下!
『叄』 如何把匯編程序嵌入到C語言中
不同編譯器嵌入匯編的方式不一樣,具體如下:
一、Turbo C, 也就是所說的TC。
1、使用預處理程序的偽指令#asm和#endasm,#asm用來開始一個匯編程序塊,而#endasm指令用於該塊的結束。
參考代碼:
intmul(inta,intb)
{
/*匯編開始*/
#asm
movax,wordptr8[bp]
imulaxwordptr10[bp]
#endasm
/*匯編結束。*/
}
2、使用asm語句:
格式:asm<匯編語句>
參考代碼:
intmul(inta,intb)
{
asmmovax,wordptr8[bp]
asmimulaxwordptr10[bp]
/*
每個asm對應一句匯編
注意結尾不需要分號
*/
}
二、VC++/VS
格式:
__asm 匯編指令 [ ; ]
__asm { 匯編指令 } [ ; ]
asm前面是兩條下劃線,後面的方括弧內容表示分號可有可無。
使用方法:
1、一條一條地用:
__asmmoval,2
__asmmovdx,0xD007
__asmoutdx,al
每行一條匯編, 可以有分號,也可以沒有。
2、組成一塊地用:
__asm{
moval,2
movdx,0xD007
outdx,al
}
整體作為一個匯編代碼塊。
3、也可以將多條匯編寫在一行:
__asmmoval,2__asmmovdx,0xD007__asmoutdx,al
三、GNU GCC
GCC對匯編的支持是最豐富的,簡單介紹如下:
1、 用到的關鍵字:
「__asm__」 表示後面的代碼為內嵌匯編,「asm」是「__asm__」的別名。
「__volatile__」表示編譯器不要優化代碼,後面的指令保留原樣,「volatile」是它的別名。
括弧裡面是匯編指令。
內嵌匯編語法如下:
__asm__(
匯編語句模板:
輸出部分:
輸入部分:
破壞描述部分)
一個簡單的匯編模板:
inta=10,b;
asm("movl%1,%%eax;
movl%%eax,%0;"
:"=r"(b)/*輸出部*/
:"r"(a)/*輸入部*/
:"%eax"/*毀壞部*/
);
表示C語言里的「b=a;」。
里邊r表示使用任意寄存器,%0、%1表示使用兩個寄存器,一般只能%0~%9共十個操作數,按輸入輸出部變數出現順序進行映射。
寄存器用兩個百分號,是因為使用了%0%1這些數字使百分號有了特殊意義,所以在操作數出現的寄存器必須用雙百分表示。
毀壞部里邊的%eax表示eax寄存器在匯編代碼塊執行過程中會被改寫,在執行前要保護好,這是提交給編譯器決定的。
『肆』 C語言中嵌入匯編,究竟有何意義
這最主要是在與硬體相關的程序中需要的,比如單片機
加入匯編,因為有的程序有非常嚴格的時序要求。
『伍』 如何C語言與匯編混編
c語言可以嵌套匯編:
按照TC2.0的幫助系統所以說的,在TC2.0下是可以用匯編的,方法是使用asm關鍵字:其格式是:
asm opcode <operands> <;newline>,如同別的注釋一樣,<>之間的表示可選的;例如:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9;asm mov dx,c;asm int 33;
printf("You sucessed!/n");
}
或者是:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9
asm mov dx,c
asm int 33
printf("You sucessed!");
}
兩種格式其實是一種.如果你用的是第一種的樣式,記住:
每一句匯編語句都要以asm開頭,如果一行內有多個句子,
那麼千萬不要忘記在兩個句子之間的這個semicolon(分號),
但是最後一句匯編後面(如果後面沒有其它的語句)的分號可有可無,象第一個例子中的
asm int 33;後面的分號就可以不要,因為它的後面沒有其它
的語句了.但如果是這樣:
asm mov ah,9; asm mov dx,c;asm int 33; printf("You sucessed!");
那麼asm int 33;後面的分號便還是留下好,以免出現編譯錯誤!
在這一點上頗象C語言.
還有一種格式是
asm{ assembly language statement},這種格式應該被普遍的歡迎.
它們的例子如下(其中的語句排列格式與上面兩種相同):
asm{
mov ax,var1
add ax,var2
......
}
但是要注意這種格式TC2.0是不支持的!
只有後來的TC++3.0及後來的IDE支持!
工具的使用:
一旦你的C源文件里包括了這些好東西,則必須用TCC.EXE的COMMAND-LINE來編譯,具體的命令參數TCC.EXE已經提供,這里不復闡述了.最簡單的是:TCC C源文件名(使用這個方法,TCC會自動調用TASM.EXE和TLINK.EXE,並且能夠使TLINK.EXE正確的找到需要的.obj和.lib文件,如果你單步編譯的話,可能會碰到很多的問題,主要是TLINK.EXE它自己並不會去找.obj和.lib文件,你自己可以建一個.bat文件,如果要指定.lib文件的目錄的話可以用/L參數,在文章的後面有一個例子).但大家要注意了,看一下你的TC目錄下面到底是否有TASM.EXE文件,並在TURBOC.CFG(這個文件包括TCC.EXE運行期參數,這裡面所有參數在運很期都將被自動TCC.EXE使用,例如:-IH:/TC/INCLUDE/
-LH:/TC/LIB/)文件中設置好一些參數,並確認TASM.EXE的版本號要2.0以上,以及是否能夠向下兼容.但是在大多數的情況下TC的目錄是沒有TASM.EXE的,或是版本不正常.
如果你有TASM.EXE文件並且TURBOC.CFG文件也已經寫好了,但是還要注意一個
問題:運行TCC.EXE時要在獨立的DOS SHELL下面(不要害怕,這不是一個新東西,我的意思
是,不在諸如TC下的DOS SHELL下面運行,我曾經敗在這個問題下,當我發現時直想揍電腦
一頓,還好沒有,不然就沒有這篇文件了.)
還有一句重要的話:TC2.0支持大部分8086指令(當然用法有一些約定,不過現在我並不打算
進行詳細說明,因為那是一件很繁雜的事,以後有時間或許會寫出來----如果大家需要的話).
如果說上面我所說的那些約定很繁雜的話,那麼下面的方法該是多麼簡單啊!
讓我們使用Borland為TC2.0內建的變數來進行偽匯編.
或許你還不知道在TC2.0中還有一些內建的pseudo寄存器(可以看作是register 型的變數,但是它們比register型的變數好用的多)
_AX,_AH,_AL,
_BX,_BH,_BL,
_CX,_CH,_CL,
_DX,_DH,_DL,
_DI,_SI,_SP,
_CS,_DS,_ES,_SS
注意這些寄存器的size,_AX,_BX,_CX,_DX,_CS,_DS,_ES,_SS,_SI,_DI,_SP等都是16位的寄存器相當於C語言的unsigned int類型,其餘的都是8位的寄存器(相當於unsigned char)(TC怎麼可能支持32位的寄存呢,所以EAX等是不能用的,FS,GS和IP寄存器都是無效的),還有就是在傳遞參數的時候千萬不要忘記使用強制類型轉換.
中斷調用指令是:__int__(interrupt_#)(注意int的前輟和後輟都是兩個underscores)
For example:
#include<dos.h>
unsigned int _stklen=0x200;
unsigned int _heaplen=0;
main()
{
_DX=(unsigned int)"Hello,world./r/n$";
_AX=0x900;
__int__(0x21);
}
dos.h它是包含__int__()內建中斷調用語句的頭文件,因此是不可
缺少的._stklen和_heaplen是定義運行期堆棧和堆大小的兩個內部
引用變數(這是個我自己想的名詞,意指如果這兩個變數在源文件中
顯式的聲明了,那麼編譯程序會自會引用來構造編譯時期的信息以產生
用戶希望的目標文件,如果不顯式的聲明則編譯程序自動確定).
這兩個變數也有一些約定,如果_stklen不顯式聲明,_heaplen賦值為零
都表示棧和堆都是defult的.
最後在TC2.0中還有一個沒有說明的標志位寄存器flags,它也是內建
pseudo寄存器是:_FLAGS,是一個16位寄存器.這些內建的寄存器都可以進行
運算,但是要注意它們所代表的類型(必要時進行類型轉換);
看起來這是不是一種好的辦法啊(而且使用這種方法只要用個一個dos.h頭文件就好,
不需要用TCC編譯,可以直接在TC20的IDE下編譯).
TC2.0中也提供了一些簡單好用的函數來實現對DOS功能的調用如:
int86(...),int86x(...)(但是這些方法實際仍然要調用函數,所以不如使用
偽寄存器,又因為要牽涉到union REGS結構的內存分配所以系統的開銷是增大了,
而使用偽寄存器是最簡潔的),埠通信函數如:inportb(...),inport(...),
outportb(...),outport(...),指針轉換函數:FP_OFF,FP_SEG,MK_FP,這些函數在
幫助系統中都有,有用時大家可以查閱.
tlinkbat.bat的例子:
rem The lib environment variable is the directory of the .obj and .lib file
set lib=h:/tc/lib/
rem 這下面的句子中的c0s(C 零S)是一個.OBJ文件,是一個C程序的STARTUP文件
tlink %lib%c0s %1,%1,%1,/L%lib%emu.lib %lib%maths.lib %lib%cs.lib
set lib=
(使用時可將以rem開頭的句子刪除)
___________________________________________________
一些約定:
我們先說一下在TC20下寫匯編(內聯匯編--自己起的名字,大家可以想叫什麼叫什麼)時的編譯器的編譯原則:
1.所有在main()函數外的的匯編語言的語句都作為數據聲明語句處理,也即在編譯器編譯時會將它放在數據段中,如:
asm string1 db "Hello",,,'world!',0ah,0xd,"$"
main()
{
asm mov dx,offset string1
asm mov ah,9
asm int 33
asm mov dx,offset string2
asm int 33
}
asm string2 db "the string can be declared after the main() function!$"
象這些樣子在main()外面的匯編語言的數據定義語句(事實上不管是什麼匯編語句,
只要是在main()之外,包括這個句子:asm mov ax,0x4c00),在編譯後都放在數據段中,而C語言的數據聲明語句仍按C的規則!
2.所有在main()函內的匯編語言的語句在編譯後都放在代碼段中,包括這個句子:
asm string2 db "the string can be declared after the main() function!$"
3.不要在以asm 開頭的語句中使用C語言的關鍵字,這會導致編譯階段的錯誤
那麼,根據這三條大家會得到什麼樣的結論呢?(先閉上眼想一想,你可能會由此變的
很贊賞自己,是的你應該這樣相信自己是對的!)
讓我們一起看一下這個結論:
1.根據編譯原則1得到:不可以在main()外面寫匯編命令語句(不要笑,正是與C語言相同才值得注意!),在任何地方都不要進行任何的段定義和宏定義(這是因為編譯後的形式決定的,也即:在TC20下所有的匯編格式的語句只能是,直接性的數據定義和語句指令)!
2根據編譯原則2得到:不可以在main()之內使用匯編的語句進行數據定義(同樣不要笑,
大多數人在第一次在TC20下寫匯編都會有這樣的錯誤的)
3.如同類強制類型這樣的事是不可以在以asm開頭的匯編語句中使用的
好了,天即朗,氣瞬清!這樣一說,一個大體的框架就出來了!只要遵守這個原則寫,就可避免很多莫名其妙的錯誤出現!
通俗的說:
匯編語句的數據定義放在main()外面,指令放在main()裡面.
如果你沒有更好的文檔,那麼記住我的這些話!
一些細節的問題:
在以asm開頭的內聯匯編語句中是不支持C的轉義字元的,但是用C語言聲明一個字元數組(含有轉義字元的),然後用int 33 ah=9這功能時輸出這個字元串時,其中的轉義字元是有效的(這主要是因為編譯後其內部表示形式不同造成的,自己想想會有答案的).
內聯匯編支持C的一些如數值表示,字元串聲明格式等,
如:一個十六進制的數據可以用兩種方式表示:0xa 和0ah,字元串可以是這樣:
"Hello,world!$"(如同C)也可以這樣'Hello,world!$'(用匯編自己的方式).
象C一樣你同樣要注意賦值的類型,而且要比C更嚴格(匯編從來不自己動手做
如同類型轉換啊這樣事),所以一切的事完全要你自己做好!而且你不要企圖以C的形式
做這件事,如這樣的格式 asm mov dx,(unsigned)a(a是一個這樣的東西,
char a[ ]="hello,world!";),而且這樣句子也會導致錯誤:asm mov dx,word ptr a(邏輯錯誤),不過這不是在編譯時的錯誤,而是運行期的錯誤(具體的原因自己想一想,象word label這樣的東西的運算作用和會導致的後果),你可以這樣用一個句子做"中間人"如int i=(unsigned)a;asm mov dx,i(也千萬不要用asm mov dx,(unsigned)a 這樣的句子.但是,告訴大家一個好消息,你可以用指針指向一個字元串,然後你會驚訝你竟然可以這樣:
char *p="hello,world";asm mov dx,p,然後用int 33 ah=9的功能輸出這個字元串而不會有錯誤(這也表現出指針的特點,它是一個二位元組的(TC20下)變數,含有的是一個地址,這與其指向的變數的類型是毫無關系的).
內匯匯編語句不支持->這個運算符.還有標號的問題,在最後的例子中你會年看到一些特別之處!
上面所說的只是很細小並微少的一些事(也是很常遇到的),尚有很多的細節要說,但由於本人時間有限不能一一列舉,如C的結構在內聯匯編的應用等大家可以按照其運行機理去想想一下用法;另外,由於這只是一件學習的事,所以還是大家自己學(找一下有關文檔,當然現在已經沒有什麼比較完整的了),情況會好的多,我在對內聯匯編的學習過程中領會到了不少的東西,例如編譯原理方面的知識,以及如何做會使代碼更高效,占空間最少等的方法.最後向大家推薦一種方法,在利用TCC的-S開關可以生成C源文件的匯編代碼
(或許很多的人都用過)是很好的學習材料!祝大家學有所成!
Cstarter
02-11-17
/* 由於個人的時間和能力有限,難免有錯誤和不詳細的地方,請大家見諒!
My Email:[email protected] [email protected] QQ:170594633 */
一些例子:
下面這個例子是對沈美明 溫冬嬋的
<<IBM-PC 匯編語言程序設計>>清華版第十一章程序的改寫
可直接在命令行上鍵入 tcc filename 就可以,當然你要有TASM.EXE
/*
asm mus_frep dw 330,294,262,294,3 p(330)
asm dw 3 p(294),330,392,392
asm dw 330,294,262,294,4 p(330)
asm dw 294,294,330,294,262,-1
asm mus_time dw 6 p(25),50
asm dw 2 p (25,25,50)
asm dw 12 p(25),100
*/
asm mus_frep dw 330,392,330,294,330,392,330,294,330
asm dw 330,392,330,294,262,294,330,392,294
asm dw 262,262,220,196,196,220,262,294,330,262
asm dw -1
asm mus_time dw 3 p (50),25,25,50,25,25,100
asm dw 2 p (50,50,25,25),100
asm dw 3 p (50,25,25),100
main()
{
asm jmp start
/*設置發聲的頻率,這一段在沈美明 溫冬嬋的
<<IBM-PC 匯編語言程序設計>>清華版第十一章有詳細的說明 */
sound:
asm mov al,0b6h
asm out 43h,al
asm mov dx,12h
asm mov ax,533h*896
asm div di
asm out 42h, al
asm mov al,ah
/* 這個延時是用來防止兩次IO操作的最後一次操作的錯誤,
因為CPU比匯流排的速度快很多,所以 要延時等待第一次操作完成後再進行第二次操作*/
asm mov cx,1000
delay:
asm loop delay
asm out 42h,al
asm in al,61h
asm mov ah,al
asm or al,3
asm out 61h,al
/* 使用中斷15H功能86H延時CX:DX=微秒數*/
asm mov ax,2710h
asm mul bx
asm mov cx,dx
asm mov dx,ax
asm mov ah,86h
asm int 15h /*可用__int__(0x15);代替*/
asm mov al,ah
asm out 61h,al
asm jmp add_count
/*------------------*/
start:
asm mov si,offset mus_frep
asm lea bp,mus_time
frep:
asm mov di,[si]
asm cmp di,-1
asm je end_mus
asm mov bx,[bp]
asm jmp sound
add_count: /*標號不能用匯編語言寫*/
asm add si,2
asm add bp,2
asm jmp frep
end_mus:;
}
對於上面的程序大家可用偽寄存器的方法寫一個,要容易的多!
/*一個發聲程序!(引自<<PC技術內幕>>電力版--這個版不好,不如清華版的)*/
#include"dos.h"
main()
{
static union REGS ourregs;
outportb(0x43,0xb6);
outportb(0x42,0xee);
outportb(0x42,0);
outportb(0x61,(inportb(0x61)|0x03));
ourregs.h.ah=0x86;
ourregs.x.cx=0x001e;
ourregs.x.dx=0x8480;
int86(0x15,&ourregs,&ourregs);
outportb(0x61,(inportb(0x61)&0xfc));
}
『陸』 C語言嵌入匯編語言
intmain(void)//C語言嵌入匯編,還是要有main函數的,而且匯編語句要放入函數裡面
{
__asmmoval,2
__asmmovdx,0xD007
__asmoutdx,al
}
『柒』 51單片機中,C語言中怎麼加入匯編語言
1、在 C 文件中要嵌入匯編代碼片以如下方式加入匯編代碼:
2、在 Project 窗口中包含匯編代碼的 C 文件上右鍵,選擇「Options for ...」,點擊右邊的「Generate Assembler SRC File」
和「Assemble SRC File」,使檢查框由灰色變成黑色(有效)狀態;
3、根據選擇的編譯模式,把相應的庫文件(如 Small 模式時,是 Keil\C51\Lib\C51S.Lib)加入工程中, 該文件必須作為工程的最
後文件;
4、編譯,即可生成目標代碼。
『捌』 c語言嵌入的匯編語句如何使用C語言定義的變數
直接用即可,比如:
『玖』 在c語言(C++或G++)中如何嵌入匯編
今天有點時間,重新改下了下,為避免因編譯器和平台實現而出現的問題,我寫了三個版本,分別是windows下vc6.0,windows下mingw和cygwin和linux下的gcc/g++。
vc6.0:
#include <stdio.h>
const char* input = "%d";
const char* output = "%d\n";
int n;
int main()
{
__asm
{
lea eax, n
push eax
push input
loopx:
call scanf
cmp eax, 1
jne end
mov ecx, n
jecxz end
dec ecx
push ecx
push output
call printf
add esp, 8
jmp loopx
end:
add esp, 8
}
return 0;
}
mingw/cygwin:
#include <stdio.h>
const char* input = "%d";
const char* output = "%d\n";
int n;
int main()
{
__asm__
(
"loop: \n"
"pushl $_n \n"
"pushl _input \n"
"call _scanf \n"
"addl $8, %esp \n"
"cmpl $1, %eax \n"
"jne end \n"
"movl _n, %ecx \n"
"jecxz end \n"
"decl %ecx \n"
"pushl %ecx \n"
"pushl _output \n"
"call _printf \n"
"addl $8, %esp \n"
"jmp loop \n"
"end:"
);
return 0;
}
linux gcc/g++:
#include <stdio.h>
const char* input = "%d";
const char* output = "%d\n";
int n;
int main()
{
__asm__
(
"pushl $n \n"
"pushl input \n"
"loop: \n"
"call scanf \n"
"cmp $1, %eax \n"
"jne end \n"
"movl n, %ecx \n"
"jecxz end \n"
"decl %ecx \n"
"pushl %ecx \n"
"pushl output \n"
"call printf \n"
"addl $8, %esp \n"
"jmp loop \n"
"end: \n"
"addl $8, %esp \n");
return 0;
}
『拾』 如何在C語言中嵌入匯編
以下所說嵌入的匯編都是GUN 的C語言中嵌入ARM匯編。
1)2個參數的內嵌語句
這種形式的匯編用於簡單的語句,參數限制輸入和輸出語法格式如下:
asm(code : output operand list : inputoperand list : clobber list);
匯編和C語句這間的聯系是通過上面asm聲明中可選的output operand list和input operand list。Clobber list後面再講。
下面是將C語言的一個整型變數傳遞給匯編,邏輯左移一位後在傳遞給C語言的另外一個整型變數。
/* Rotating bits example */
asm("mov %[result], %[value], ror#1" : [result] "=r" (y) : [value] "r" (x));
每一個asm語句被冒號(:)分成了四個部分。
匯編指令放在第一部分中的「」中間。
"mov %[result], %[value], ror #1"
接下來是冒號後的可選擇的output operand list,每一個條目是由一對[](方括弧)和被他包括的符號名組成,它後面跟著限制性字元串,再後面是圓括弧和它括著的C變數。這個例子中只有一個條目。
[result] "=r" (y)
接著冒號後面是輸入操作符列表,它的語法和輸入操作列表一樣
[value] "r" (x)
為了增加代碼的可讀性,你可以使用換行,空格,還有C風格的注釋。
asm("mov %[result], %[value], ror#1"
: [result]"=r" (y) /* Rotation result. */
: [value]"r" (x) /* Rotated value. */
: /* No clobbers */
);
在代碼部分%後面跟著的是後面兩個部分方括弧中的符號,它指的是相同符號操作列表中的一個條目。
%[result]表示第二部分的C變數y,%[value]表示三部分的C變數x;
符號操作符的名字使用了獨立的命名空間。這就意味著它使用的是其他的符號表。簡單一點就是說你不必關心使用的符號名在C代碼中已經使用了。在早期的C代碼中,循環移位的例子必須要這么寫:
asm("mov %0, %1, ror #1" :"=r" (result) : "r" (value))
在匯編代碼中操作數的引用使用的是%後面跟一個數字,%1代表第一個操作數,%2代碼第二個操作數,往後的類推。這個方法目前最新的編譯器還是支持的。但是它不便於維護代碼
實例代碼:
2) 帶.s文件的匯編
編譯命令:
arm-linux-gcc main.cAsmfile_gnu.s -o mains
main.c
#include<stdio.h>
extern voidpcm8_2_pcm16(unsigned char* pIn, int nInlen, short* pOut);
extern voidpcm16_2_pcm8(short* pIn, int nInlen,unsigned char* pOut);
int main()
{
unsigned char* pIn="1234";
short pInd[256];
unsigned char pOutd[256];
int nInlen=4;
int i = 0;
short pOut[256];
for(i=0;i<4;i++)
printf(" 0x%x ",pIn[i]);
printf(" ");
memset((char *)pOut,0,256*2);
memset((char *)pInd,0,256*2);
memset((char *)pOutd,0,256*2);
pcm8_2_pcm16(pIn,nInlen,pOut);
for(i=0;i<4;i++)
printf(" 0x%x ",pOut[i]);
printf(" ");
memcpy((char *)pInd,(char *)pOut,256*2);
pcm16_2_pcm8(pInd,nInlen,pOutd);
for(i=0;i<4;i++)
printf(" 0x%x ",pOutd[i]);
printf(" ");
return 0;
}
Asmfile_gnu.s
.text
.global pcm8_2_pcm16
.global pcm16_2_pcm8
#*******************************#
#********* ENCODER 實現將第一個輸入參數
#左移8位然後異或0x8000 然後拷貝到第三個參數
#DECODE 取第一個參數所指的數據先異或0x8000
#然後右移8位將數據拷貝到第三個參數
#*******************************
pcm8_2_pcm16:
MOV R6,#0
MOV R7,#0
ENCODER:
LDRB R5,[R0,R6]
MOV R8,R5,LSL#8
EOR R9,R8,#0x8000
STRH R9,[R2,R7]
ADD R7,R7,#2
ADD R6,R6,#1
SUB R1,R1,#1
CMP R1,#0
BNE ENCODER
B OVER
pcm16_2_pcm8:
MOV R6,#0
MOV R7,#0
DECODE:
LDRH R5,[R0,R6]
EOR R8,R5,#0x8000
MOV R9,R8,LSR#8
STRB R9,[R2,R7]
ADD R7,R7,#1
ADD R6,R6,#2
SUB R1,R1,#1
CMP R1,#0
BNE DECODE
OVER:
.end