汇编语言参数传递共26页文档

合集下载

汇编语言程序设计-数据传输指令

汇编语言程序设计-数据传输指令

一、数据传输指令───────────────────────────────────────它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.1. 通用数据传送指令.MOV 传送字或字节.MOVSX 先符号扩展,再传送.MOVZX 先零扩展,再传送.PUSH 把字压入堆栈.POP 把字弹出堆栈.PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.BSW AP 交换32位寄存器里字节的顺序XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD 先交换再累加.( 结果在第一个操作数里)XLAT 字节查表转换.── BX 指向一张256 字节的表的起点, AL 为表的索引值(0-255,即0-FFH); 返回AL 为查表结果. ( [BX+AL]->AL )2. 输入输出端口传送指令.IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器)输入输出端口由立即方式指定时, 其范围是0-255; 由寄存器DX 指定时,其范围是0-65535.3. 目的地址传送指令.LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.4. 标志传送指令.LAHF 标志寄存器传送,把标志装入AH.SAHF 标志寄存器传送,把AH内容装入标志寄存器.PUSHF 标志入栈.POPF 标志出栈.PUSHD 32位标志入栈.POPD 32位标志出栈.二、算术运算指令───────────────────────────────────────ADD 加法.ADC 带进位加法.INC 加1.AAA 加法的ASCII码调整.DAA 加法的十进制调整.SUB 减法.SBB 带借位减法.DEC 减1.NEC 求反(以0 减之).CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).AAS 减法的ASCII码调整.DAS 减法的十进制调整.MUL 无符号乘法.IMUL 整数乘法.以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算), AAM 乘法的ASCII码调整.DIV 无符号除法.IDIV 整数除法.以上两条,结果回送:商回送AL,余数回送AH, (字节运算);或商回送AX,余数回送DX, (字运算).AAD 除法的ASCII码调整.CBW 字节转换为字. (把AL中字节的符号扩展到AH中去) CWD 字转换为双字. (把AX中的字的符号扩展到DX中去) CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去) CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)三、逻辑运算指令───────────────────────────────────────AND 与运算.or 或运算.XOR 异或运算.NOT 取反.TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果). SHL 逻辑左移.SAL 算术左移.(=SHL)SHR 逻辑右移.SAR 算术右移.(=SHR)ROL 循环左移.ROR 循环右移.RCL 通过进位的循环左移.RCR 通过进位的循环右移.以上八种移位指令,其移位次数可达255次.移位一次时, 可直接用操作码. 如SHL AX,1.移位>1次时, 则由寄存器CL给出移位次数.如MOV CL,04SHL AX,CL四、串指令───────────────────────────────────────DS:SI 源串段寄存器:源串变址.ES:DI 目标串段寄存器:目标串变址.CX 重复次数计数器.AL/AX 扫描值.D标志0表示重复操作中SI和DI应自动增量; 1表示应自动减量. Z标志用来控制扫描或比较操作的结束.MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. ) CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位. LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )STOS 保存串.是LODS的逆过程.REP 当CX/ECX<>0时重复.REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复. REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复. REPC 当CF=1且CX/ECX<>0时重复.REPNC 当CF=0且CX/ECX<>0时重复.五、程序转移指令───────────────────────────────────────1>无条件转移指令(长转移)JMP 无条件转移指令CALL 过程调用RET/RETF过程返回.2>条件转移指令(短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )JA/JNBE 不小于或不等于时转移.JAE/JNB 大于或等于转移.JB/JNAE 小于转移.JBE/JNA 小于或等于转移.以上四条,测试无符号整数运算的结果(标志C和Z).JG/JNLE 大于转移.JGE/JNL 大于或等于转移.JL/JNGE 小于转移.JLE/JNG 小于或等于转移.以上四条,测试带符号整数运算的结果(标志S,O和Z).JE/JZ 等于转移.JNE/JNZ 不等于时转移.JC 有进位时转移.JNC 无进位时转移.JNO 不溢出时转移.JNP/JPO 奇偶性为奇数时转移.JNS 符号位为"0" 时转移.JO 溢出转移.JP/JPE 奇偶性为偶数时转移.JS 符号位为"1" 时转移.3>循环控制指令(短转移)LOOP CX不为零时循环.LOOPE/LOOPZ CX不为零且标志Z=1时循环.LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.JCXZ CX为零时转移.JECXZ ECX为零时转移.4>中断指令INT 中断指令INTO 溢出中断IRET 中断返回5>处理器控制指令HLT 处理器暂停, 直到出现中断或复位信号才继续.WAIT 当芯片引线TEST为高电平时使CPU进入等待状态. ESC 转换到外处理器.LOCK 封锁总线.NOP 空操作.STC 置进位标志位.CLC 清进位标志位.CMC 进位标志取反.STD 置方向标志位.CLD 清方向标志位.STI 置中断允许位.CLI 清中断允许位.六、伪指令───────────────────────────────────────DW 定义字(2字节).PROC 定义过程.ENDP 过程结束.SEGMENT 定义段.ASSUME 建立段寄存器寻址.ENDS 段结束.END 程序结束.七、处理机控制指令:标志处理指令CLC(进位位置0指令)CMC(进位位求反指令)STC(进位位置为1指令)CLD(方向标志置1指令)STD(方向标志位置1指令)CLI(中断标志置0指令)STI(中断标志置1指令)NOP(无操作)HLT(停机)WAIT(等待)ESC(换码)LOCK(封锁)MOV(MOVe)传送指令PUSH 入栈指令POP 出栈指令XCHG(eXCHanG)交换指令XLAT(TRANSLATE)换码指令LEA (Load Effective Address)有效地址送寄存器指令LDS(Load DS with pointer)指针送寄存器和DS指令LES(Load ES with pointer)指针送寄存器和ES指令LAHF(Load AH with Flags)标志位送AH指令SAHF(Store AH into Flgs)AH送标志寄存器指令PUSHF(PUSH the Flags)标志进栈指令POPF(POP the Flags)标志出栈指令ADD 加法指令ADC 带进位加法指令INC 加1指令SUB(SUBtract)不带借位的减法指令SBB(SuVtrach with borrow)带借位的减法指令DEC(DECrement)减1指领NEG(NEGate)求补指令CMP(CoMPare)比较指令MUL(unsinged MULtiple)无符号数乘法指令IMUL(sIgned MUL tiple)有符号数乘法指令DIV(unsigned DIVide)无符号数除法指令IDIV(sIgned DIVide)有符号数除法指令CBW(Count Byte to Word)字节转换为字指令CWD(Count Word to Doble word)字转换为双字指令DAA 压缩的BCD码加法十进制调整指令DAS 压缩的BCD码减法十进制调整指令AAA 非压缩的BCD码加法十进制调整指令AAS 非压缩的BCD码加法十进制调整指令AND 逻辑与指令OR 逻辑或指令XOR 逻辑异或指令NOT 逻辑非指令TEST 测试指令SHL(SHift logical Letf)逻辑左移指令SHR(SHift logical Right)逻辑右移指令ROL(Rotate Left )循环左移指令P58ROR(Rotate Right)循环右移指令P58RCL(Rotate Left through Carry)带进位循环左移RCR(Rotate Right through Carry)带进位循环左移MOVS(MOVe String)串传送指令STOS(STOre into String)存入串指令LODS(LOad from string)从串取指令REP(REPeat)重复操作前CLD(CLear Direction flag)清除方向标志指令STD(SeT Direction flag)设置方向标志指令CMPS(CoMPare String)串比较指令SCAS(SCAn String)串扫描指令REPE/REPZ(REPeat while Equal/Zero)相等/为零时重复操作前缀REPNE/REPNZ(REPeat while Not Equal/Zero)不相等/不为零进重复前缀IN(INput)输入指令OUT(OUTput)输出指令JMP(JuMP)无条件转移指令JZ,JNZ,JS,JNS,JO,JNO,JP,JNP,JB,JNB,JBE,JNBE,JL,JNL,JLE,JNLE,JCXZ 条件转移指令LOOP 循环指令P70LOOPZ/LOOPE 为零/相等时循环指令LOOPNZ/LOOPNE 不为零/不相等时循环指令CALL 子程序调用指令RET(RETun)子程序返回指令CLC(CLear Carry)进位位置0指令CMC(CoMplement Carry)进位位求反指令SRC(SeT Carry)进位位置1指令NOP(No OPeretion)无操作指令HLT(HaLT)停机指令OFFSET 返回偏移地址SEG 返回段地址EQU(=) 等值语句PURGE 解除语句DUP 操作数字段用复制操作符SEGMENT,ENDS 段定义指令ASSUME 段地址分配指令ORG 起始偏移地址设置指令$ 地址计数器的当前值PROC,ENDP 过程定义语句NAME,TITLE,END 程序开始结束语句MACRO,ENDM 宏定义指令JZ OPR //结果为零转移JNZ OPR //结果不为零转移JS OPR //结果为负转移JNS OPR //结果为正转移JO OPR //溢出转移JNO OPR //不溢出转移JP OPR //结果为偶转移JNP OPR //结果为奇转移JC OPR //有进位转移JNC OPR //无进位转移。

第3节1数据传送指令

第3节1数据传送指令

长格式: OUT PORT, AL (字节)
OUT PORT, AX (字)
执行操作:( PORT ) (AL)
(字节)
( PORT+1, PORT ) (AX)(字)
短格式: OUT DX, AL (字节)
OUT DX, AX (字)
执行操作:( (DX) ) (AL)
(字节)
( (DX)+1, (DX) ) (AX)(字)
SRC是源操作数,可以是寄存器、存储单元或立即数。
(1)立即数传送给通用寄存器或存储单元 例如:MOV BL,44 MOV AX,3450H MOV WORD PTR [DI],2178H MOV BYTE PTR [DI],32H
ቤተ መጻሕፍቲ ባይዱ注意
不影响标志位。 立即数、CS和IP不能 做目的操作数
(2) 通用寄存器之间相互传送 MOV SI,DI MOV AL,BH
例: IN AX, 28H MOV DATA_WORD, AX
;IN BX,28H?
例: MOV DX, 3FCH IN AX, DX
例: OUT 5, AL;与MOV 5, AL比较
例:测试某状态寄存器(端口号27H)的第2位是否为1
IN
AL, 27H
TEST AL, 00000100B
JNZ ERROR
重点关注:
• 指令的汇编格式 • 指令的基本功能 • 指令支持的寻址方式 • 指令的执行对标志位的影响 • 指令的特殊要求
3.3 8086指令系统
3.3.1数据传送指令
数据传送指令的功能是将数据、地址或立即数传送到寄存器或存储单元中。
1.通用数据传送指令 格式: MOV DST ,SRC

SDCC的MCS-51汇编基础概念和传参方式

SDCC的MCS-51汇编基础概念和传参方式

SDCC的MCS-51汇编基础概念和传参⽅式寄存器 Register寄存器⽤于数据的临时存储, 其数据可以表⽰为⽤于处理的数据字节指向数据的地址寄存器的结构8051的寄存器⼏乎都是8位寄存器, 因为8位MCU处理的主要是8位数据, 如果数据⼤于8位, 则需要拆成多段分别处理. ⼀个8位的寄存器, 从D7到D0代表起第7位到第0位, D7这端为MSB(most significant bit), D0这端为LSB(least significant bit).常⽤寄存器A (累加器)B, R0, R1, R2, R3, R4, R5, R6, R7 在函数中使⽤的变量, R0-R7是变量, 地址并⾮唯⼀, 其绝对地址由AR0-AR7指定.DPTR(data pointer), PC(program counter) 这两个都是16位双字节寄存器PC 指向下⼀个指令的地址, 16位宽度, 因此代码区的最⼤范围为0 - 0xFFFF, 64K字节8051启动时, PC值为0x0000, 从代码区0x0000开始执⾏第⼀条指令SP 栈顶指针, 其值为堆栈栈顶的地址, SDCC中, 堆栈的地址是向上增长的, 这个与常见的向下增长不同BP 基址指针寄存器BP(base pointer), 和堆栈指针SP联合使⽤, 使⽤BP把SP的值传递给BP, 通过BP来寻找堆栈⾥数据或者地址.程序状态寄存器 PSW其中的6个位是预先定义的, 分别为CY 最⾼位进位标志位, 当加法等运算结果超过0xFF, 产⽣进位时, 这个bit会被置1AC D3 ⾄ D4 进位标志位, 当加法等运算低四位产⽣仅位时, 这个bit会被置1F0RS1 寄存器组选择, RS1,RS0的组合对应的选择为RS0 寄存器组选择: 0,0:bank0, 0,1:bank1, 1,0:bank2, 1,1:bank3OV 溢出标志位--P 奇偶校验位, 如果在寄存器A中的, 1的个数为偶数时这个bit为0, 1的个数为奇数时这个bit为1内存结构8051的基础内存为128字节, 地址为00H - 7FH, 这128字节被分成三组1. 00H - 1FH, 32个字节, ⽤于寄存器组和堆栈这32个字节被分成4组(4 banks), 每组8个寄存器R0-R7当8051加电时, 默认使⽤寄存器组0(bank 0)通过PWS的D4,D3选择栈顶地址存储在SP寄存器SP寄存器只有8位, 因此其范围只有00H-FFH当8051加电时, SP寄存器的值为07, 因此内存地址08H就是堆栈的第⼀个地址, 这个地址与寄存器组1是重合的可以给堆栈指定其它的地址PUSH操作时, SP会加1, 向上增长POP操作时, SP减1, 向下收缩2. 20H - 2FH, 16个字节⽤于可以按位寻址内存访问3. 30H - 7FH, 80个字节属于通⽤内存(scratch pad)寄存器操作⽰例MOV 赋值操作格式为 MOV destination, source赋值操作有⼏种类型直接数赋值将值0x55赋值给寄存器AMOV A,#55H直接数可以赋值的寄存器为A, B, R0-R7如果给寄存器赋值 #0 ⾄ #F, 等价于赋值 #00H ⾄ #0FH如果直接数超过8位数值, 会产⽣错误寄存器赋值将寄存器A的值赋值给R0MOV R0,A地址赋值将R0中存储的值作为地址, 这个地址存储的值赋值给AMOV A,@R0加法操作ADD A, source将source的值与A相加, 结果存储在Asource可以是寄存器或直接数, 但是结果⼀定存储在寄存器AADD的第⼀个参数, ⽬标寄存器必须A例如计算 #25H + #34HMOV A, #25H ;load one operand;into A (A=25H)ADD A, #34H ;add the second;operand 34H to ASDCC汇编语⾔基础概念汇编语⾔的指令格式为[label:] Mnemonic [operands] [;comment]汇编语⾔的编译过程1. ⽂本汇编程序, file.asm2. 汇编编译, 产⽣lst⽂件 file.lst 和 obj⽂件 file.obj3. 连接器, 产⽣abs⽂件, file.abs4. Object to Hex转换, 产⽣hex⽂件, file.hex如果使⽤VSCode + PlatformIO开发, 可以在项⽬的 .pio ⽬录下看到这些⽂件LST⽂件lst(list)⽂件对于开发者⾮常有⽤, 在⾥⾯会按⾏显⽰每⼀句汇编语句对应的机器指令, 及其在代码区的偏移位置. 可以检查语法错误已经debug 分析.伪指令DB: ⽤于定义数据, 可以是⼗进制数, ⼆进制数, ⼗六进制数, ASCII等ORG(origin): ⽤于指定起始地址END: 标识代码结束EQU(equate): ⽤于定义常量SDCC汇编函数参数传递第⼀个参数和返回值编译器总是使⽤全局寄存器 DPL, DPH, B 和 ACC 传递第⼀个函数参数(必须是⾮bit型参数)和传递函数返回结果1个字节返回值存储在DPL2个字节: DPL(LSB)和DPH(MSB)3个字节(通⽤指针): DPH, DPL和 B4个字节: DPH, DPL, B 和 ACC在 B 中存储通⽤指针的类型:0x00 – xdata/far, 外部数据存储0x40 – idata/near – , 内部数据存储0x60 – pdata, 外部数据存储0x80 – code, 代码区bit型参数, 位参数在可重⼊函数中, 位参数在位可寻址空间中被传递到虚拟寄存器bits中其它的情况, 直接在位内存中存储第⼆个之后的参数第⼆个参数可以在堆栈上存储(reentrant 或者使⽤ --stack-auto ), 也可以在数据/xdata存储器中存储(取决于存储器型号)可重⼊函数对于通过函数指针调⽤, 并且带两个或两个以上参数的函数, 必须是可重⼊的, 这样编译器才能正确地传递参数.相关寄存器的说明除⾮函数被定义为 _naked 或 --callee-saves/--all-callee-saves 或者使⽤了 callee_saves pragma, 调⽤⽅会在调⽤前后对寄存器 R0-R7 的值进⾏保护和恢复, 所以被调⽤的函数可以随意读写 R0-R7.并且如果函数未被定义为 _naked, 如果调⽤⽅和被调⽤函数使⽤了不同的寄存器组(register banks, 使⽤ __using 声明), 调⽤⽅会在调⽤前后处理寄存器组的切换.被调⽤的函数使⽤ DPL, DPH, B 和 ACC 获取参数和存储返回结果⽰例说明⾮重⼊的函数调⽤在 C 语⾔⾥, 调⽤函数时会将函数参数以及函数的局部变量放⼊堆栈, 但是由于8位MCS-51芯⽚内部堆栈空间有限, ⽆法像 windows/unix 那样使⽤堆栈, 所以⽆法使⽤这种⽅式, ⽽是为每个函数的局部变量和参数申请⼀个空间来存放.下⾯的例⼦是⼀个简单的函数int test(int a, int b)⽤于计算 a 与 b 的和并返回. 其中第⼀个参数⽤ DPL, DPH, B, ACC 传递(从LSB -> MSB), a 是双字节, 所以存储在 DPL, DPH第⼆个参数⽤全局变量传递_test_PARM_2;--------------------------------------------------------; Public variables in this module;--------------------------------------------------------.globl _test_PARM_2.globl _test;--------------------------------------------------------; overlayable items in internal ram;--------------------------------------------------------.area OSEG (OVR,DATA) ; DATA area 0x00 ~ 0x80, 可重叠的空间_test_PARM_2:.ds 2 ; 预留的空间, 2字节;--------------------------------------------------------; code;--------------------------------------------------------.area CSEG (CODE);------------------------------------------------------------;Allocation info for local variables in function 'test';------------------------------------------------------------;b Allocated with name '_test_PARM_2';a Allocated to registers r6 r7;c Allocated to registers;------------------------------------------------------------; src/st7567_stc8h3k.c:32: int test(int a, int b); -----------------------------------------; function test; -----------------------------------------_test:ar7 = 0x07 ; ar0-ar7表⽰当前选中的寄存器组r0-r7的寄存器绝对地址,; 这⾥将r0-r7的地址设置为00H到07Har6 = 0x06ar5 = 0x05ar4 = 0x04ar3 = 0x03ar2 = 0x02ar1 = 0x01ar0 = 0x00mov r6,dpl ; 将第⼀个参数存⼊ r6, r7mov r7,dph; src/st7567_stc8h3k.c:34: int c = a + b;mov a,_test_PARM_2 ; 将第⼆个参数的LSB存⼊aadd a,r6 ; 低8位相加mov dpl,a ; 结果存⼊DPLmov a,(_test_PARM_2 + 1) ; 将第⼆个参数的MSB存⼊aaddc a,r7 ; ⾼8位相加, 带前⼀次运算的进位mov dph,a ; 结果存⼊DPH; src/st7567_stc8h3k.c:35: return c;; src/st7567_stc8h3k.c:36: }ret从main中调⽤时, 第⼀个参数存⼊DPL, DPH, 第⼆个参数存⼊_test_PARM_2和_test_PARM_2 + 1mov _test_PARM_2,r4mov (_test_PARM_2 + 1),r5mov dpl,r6mov dph,r7lcall _test可重⼊的函数调⽤SDCC 将局部变量放到全局变量中后, 相当于成为了静态变量, 因此⽆法在递归函数中使⽤(⽆法重⼊), 并且在 interrupt function 中不能调⽤,因为当中断发⽣在这些函数中时就会发⽣重⼊,造成局部变量被修改, 造成不可预期的结果. 所以对于这类场景, 需要在函数上加上__reentrant关y键词. 此时编译器会将局部变量放到堆栈上. 在这种情况下, 第⼆个及之后的参数将被放在堆栈中,参数从右到左依次⼊栈, 因此第⼆个参数总是最后⼀个⼊栈, 在堆栈的顶部.下⾯的例⼦还是上⾯的简单函数int test(int a, int b), 但是加了__reentrant关键词.在函数的⼊⼝, 旧的 _bp 被⼊栈, 之后 SP 的值被复制给 _bp, 如果在堆栈上有局部变量, 也会在 SP 上存储, 此时 _bp 指向的是堆栈上的第⼀个局部变量, 参数则存储在更低的地址上.sp是栈指针, 如果不保存的话就⽆法返回调⽤它的程序,因为下⾯要改变栈指针, 所以不能⽤⼊栈的⽅法保存, 只能保存在寄存器中bp这个寄存器是专门在栈段操作在栈区的⼦程序的临时变量⽤的, 很⽅便, 所以⽤bp保存sp的内容;--------------------------------------------------------; Public variables in this module;--------------------------------------------------------.globl _test ; 可以看到, 只有函数声明, 没有参数⼆的声明; 也没有.area OSEG中对参数⼆的存储预留;--------------------------------------------------------; code;--------------------------------------------------------.area CSEG (CODE);------------------------------------------------------------;Allocation info for local variables in function 'test';------------------------------------------------------------;b Allocated to stack - _bp -4 ; 参数⼆被放到了 _bp -4 位置,; 如果还有参数三, 并且也是int, 会被放到 _bp -6 的位置;a Allocated to registers r6 r7;c Allocated to registers;------------------------------------------------------------; src/st7567_stc8h3k.c:32: int test(int a, int b) __reentrant; -----------------------------------------; function test; -----------------------------------------_test:ar7 = 0x07 ; ar0-ar7表⽰当前选中的寄存器组r0-r7的寄存器绝对地址, 这⾥将r0-r7的地址设置为00H到07Har6 = 0x06ar5 = 0x05ar4 = 0x04ar3 = 0x03ar2 = 0x02ar1 = 0x01ar0 = 0x00push _bp ; 将堆栈帧指针⼊栈, 原来栈顶是返回地址, _bp⼊栈后, 栈顶变成了:; _bp, 返回地址, 参数⼆, 因为⼊栈动作, 栈顶地址增长了(SDCC中堆栈地址是往上增长的),; SP指向了新的栈顶地址mov _bp,sp ; 将此时的栈顶赋值给_bp, 注意, 这时候_bp⾥保存的变成了⼀个地址, 栈顶的地址.mov r6,dpl ; 将参数⼀放⼊r6, r7mov r7,dph; src/st7567_stc8h3k.c:34: int c = a + b;mov a,_bp ; 将_bp值赋值给a, 此时a⾥⾯存了栈顶地址add a,#0xfc ; 8bit数加0xfc就等于减4, 得到最后⼀个参数的指针, 这⾥第⼆个参数就是最后⼀个参数mov r0,a ; 结果赋值给r0mov a,@r0 ; 将r0作为地址, 取到的值赋值给aadd a,r6 ; 与r6相加(低8位)mov r6,a ; 结果存回r6inc r0 ; r0++(下⼀个字节的地址)mov a,@r0 ; 将r0作为地址, 取到的值赋值给aaddc a,r7 ; 与r7相加(⾼8位), 带前⼀步的进位mov r7,a ; 将结果存回r7mov dpl,r6 ; 将返回结果存到dpl, dphmov dph,r7; src/st7567_stc8h3k.c:35: return c;; src/st7567_stc8h3k.c:36: }pop _bp ; 在返回前, 恢复堆栈指针ret从main中调⽤这个函数, 在调⽤后恢复栈顶指针push ar4 ; 参数⼆⼊栈push ar5mov dpl,r6 ; 参数⼀赋值给DPTRmov dph,r7lcall _test ; 调⽤(此时会将返回地址⼊栈)dec sp ; 此时恢复到了调⽤前的栈顶地址, 再dec两次抵消掉参数⼆⼊栈产⽣的地址增长, 恢复栈顶位置dec sp在汇编的 reentrant 函数开头, 有⼀个变量_bp, 这个变量在 sdcc/lib/src/_bp.c 中声明, 是基址指针寄存器, ⽤来计算进⼊堆栈的参数和局部变量的偏移._bp is the stack frame pointer and is used to compute the offset into the stack for parameters and local variables.基址指针寄存器BP(base pointer)的⽤途⽐较特殊, 是和堆栈指针SP联合使⽤的, 例如在带参数的⼦过程中⽤BP来获取参数和访问设在堆栈⾥⾯的临时变量. 例如堆栈中压⼊了数据或者地址, 如果想访问这些数据或者地址, 但SP指向栈顶, 不能随便乱改, 并且SP会随着带有堆栈操作(PUSH, CALL, INT, RETF)⽽变化, 这时候可以使⽤BP, 把SP的值传递给BP, 通过BP来寻找堆栈⾥数据或者地址.参考SDCC使⽤⼿册关于_BP和重⼊。

混合编程及参数传递的方法

混合编程及参数传递的方法

混合编程及参数传递的方法在编程中,对于实时性要示较高的采用汇编语言编程比较合适,对复杂的计算或实时性要求不高,且对C语言编程比较合适。

但在实际开发时,针对硬件要求实时性比较强且计算比较复杂的,可以采用联合设计方式,即混合编程,以发挥汇编语言和C语言各自的长处。

一、编程举例在一个项目中加入汇编语言程序有两种方法:一种方法是使用Inline assembly;另一种方法是将汇编程序写在一个文件中,然后再从主程序中调用这些用汇编语言编写的子程序。

以下分别进行介绍。

1。

使用Inline assembly,也就是在程序中直接加入汇编语言代码。

例如:…V oid callasm(){#pragma asm;Delay:MOV R0,#248;DJNZ R0,$#pragma endasm;}…直接加入汇编语言代码时,使用编译指令#pragma asm 和#pragma endasm 。

编译指令#pragma asm 和#pragma endasm之间加入汇编语言代码。

2。

将汇编程序写入在一个文件中,再从主程序中调用这些使用汇编语言写的子程序。

例如:C语言代码段:#include<reg52.h>Extern void callasm ();//声明外部汇编函数callasmV oid main(){Uchar temp;….Callasm();….}汇编语言代码段:PUBLIC _CALLASM;//CALLASM 为其他模块调用DE SEGMENT CODE;//定义DE段为再定位程序段RSEG DE;选择DE为当前段……¬_CALLASM:Delay:MOV R0,#248;DJNZ R0,$RETEND二、C语言程序和汇编语言程序参数的传递上述两种方法都存在C语言代码段和汇编语言代码段参数传递的问题。

下面分别介绍。

KEIL C51编译器可以使用寄存器传递参数,也可以使用固定存储器或使用堆栈。

数据传送指令PPT课件

数据传送指令PPT课件
例3 若(A)=23H,执行MOV R1,A ,则R1的内 容为多少 (R1)=23H
.
以direct 为目的操作数的指令
1、指令 MOV direct, @Rn MOV direct,A MOV direct,#data MOV direct,Rn MOV direct,direct
.
2、功能 把源操作数送入由直接地址指向的存储
【作业】
1、设(A)=34H,(R0)=30H,(30H)=56H, 执行下列指令后A的内容是多少? XCHD A,@R0
2、若(R0)=37H,(A)=76H,执行 XCH A, R0 指令 结果:(A)=?,(R0)=?
3、设(SP)=32H,(32H)=70H,(31H) =60H,执行下述指令后SP是多少?
1、若(23H)= 30H,执行 MOV R6,23H 则 R6的内容为多少,该指令的寻址方式是什么?
2、若执行MOV R3,#24H , 则结果:(R3) =?
3、若(40H)=34H ,执行MOV A ,40H, 则结果: (A)=?
.
作业:
1、若(R1)= 30H,(30H)= 68H,执行 MOV A,@R1,则A的内容为多少,源操作数 的寻址方式是什么?
2、若执行MOV R1,#20H ,则R1的内容为多少 3、若(64H)=70H,(A)=78H,执行指令MOV
64H,A 则64H及A的内容为多少 4、若(R1)=35H,执行 MOV @R1,#40H 指
令则35H的内容为多少
.
用户RAM区或堆栈区(见教材P49)
• 供用户使用的一般RAM区,共有80个单 元,其单元地址为30H~7FH。在一般应用 中常把堆栈开辟在此区中。MCS—51单片机 堆栈区不是固定的, 原则上可设在内部RAM 的任意区域内, 但为了避开工作寄存器区 和位寻址区, 一般设在30H以后的范围内。

汇编语言程序设计第二版

汇编语言程序设计第二版

汇编语言程序设计第二版汇编语言是一种低级编程语言,它使用助记符来表示机器指令,允许程序员直接控制硬件。

汇编语言程序设计第二版是针对那些希望深入理解计算机系统底层工作机制的程序员和计算机科学学生编写的教材。

本书在第一版的基础上进行了更新和扩充,以适应现代计算机体系结构和编程实践的发展。

第一章:汇编语言基础本章介绍了汇编语言的基本概念,包括指令集、寄存器、内存寻址方式以及指令的格式和操作。

通过实例代码,读者可以初步了解如何使用汇编语言编写简单的程序。

第二章:数据表示和运算数据在计算机中的表示是程序设计的基础。

本章详细讨论了不同数据类型(如整数、浮点数和字符)在汇编语言中的表示方法,以及基本的算术和逻辑运算。

第三章:程序控制结构程序控制结构是程序设计中的重要组成部分。

本章讲解了条件语句、循环、跳转等控制结构在汇编语言中的实现方式,并通过实际例子展示了如何使用这些结构来编写更复杂的程序。

第四章:子程序和参数传递子程序是程序设计中常用的模块化技术。

本章介绍了如何在汇编语言中定义和调用子程序,以及参数传递的机制。

此外,还讨论了堆栈的使用和调用约定。

第五章:输入输出和中断处理现代计算机系统通常需要与外部设备交互。

本章讲解了汇编语言中实现输入输出的方法,包括直接内存访问(DMA)和中断驱动的I/O。

同时,介绍了中断服务程序的编写。

第六章:高级汇编技术随着计算机技术的发展,汇编语言也引入了一些高级技术,如宏定义、条件汇编和模块化编程。

本章对这些高级技术进行了深入的探讨,并提供了相应的编程实例。

第七章:系统级编程系统级编程涉及到操作系统的底层接口。

本章介绍了如何在汇编语言中实现系统调用,以及如何处理进程和线程的创建和管理。

第八章:性能优化性能是程序设计中的一个重要考虑因素。

本章讨论了汇编语言程序的性能优化技巧,包括指令选择、循环展开和流水线优化等。

第九章:安全性和可维护性随着软件安全和可维护性的重要性日益增加,本章讨论了在汇编语言编程中如何实现代码的安全性和可维护性,包括错误处理、异常处理和代码审查。

汇编语言 PPT课件

汇编语言 PPT课件

;宏定义
shlext macro shloprand,shlnum
push cx
mov cl,shlnum
shl shloprand,cl
pop cx
endm
;宏指令
shlext ax,6
;宏展开
1
push cx
1
mov cl,06
1
shl ax,cl
1
pop cx
例5.5a
;统一4条移位指令的宏指令
xor al,al
sumd: add al,bx ;求和:AL←AL+DS:BX
inc bx
loop sumd
ret
checksumd endp end
列表文件
第5章
5.2 宏结构程序设计
宏汇编 重复汇编 条件汇编 ——统称宏结构
宏 Macro 是汇编语言的一个特点, 它是与子程序类似又独具特色的另一 种简化源程序的方法
例5.10
;;如果num < 100,则汇编如下语句 ;;否则,汇编如下语句
pdata 12 db 12 dup
pdata 102 db 100 dup
;宏调用① ;宏汇编结果①
;宏调用② ;宏汇编结果②
宏汇编、重复汇编和条件汇编
为源程序的编写提供了很多方便,
灵活运用它们可以编写出非常

良好的源程序来
例题5.4-2/3 mainend MACRO retnum ;;返回DOS,可不带参数
ifb <retnum> mov ah,4ch ;;没有参数
else mov ax,4c00h+ retnum AND 0ffh
;; 有参数 endif int 21h ENDM

c语言与8086汇编语言的相互调用及参数传递

c语言与8086汇编语言的相互调用及参数传递

c语言与8086汇编语言的相互调用及参数传递C语言与8086汇编语言的相互调用及参数传递在计算机科学领域中,C语言和8086汇编语言是两种非常重要的编程语言。

C语言以其简洁、高效和易读的特点被广泛应用于系统开发和应用程序编写,而8086汇编语言则是一种底层的编程语言,可以直接访问计算机硬件资源。

在某些特定的应用场景下,需要将这两种语言结合起来使用,以发挥各自的优势。

本文将详细介绍C语言和8086汇编语言之间的相互调用方法,以及参数在两种语言之间的传递方式。

我们将从基本概念开始,逐步讲解相关知识点。

一、C语言调用汇编函数C语言调用汇编函数的方法可以分为两种:使用内联汇编和使用外部汇编文件。

1. 使用内联汇编内联汇编是将汇编代码直接嵌入到C语言程序中的一种方法。

它的语法相对简单,在适当的地方插入汇编代码即可。

下面是一个使用内联汇编调用汇编函数的示例:c#include <stdio.h>extern void assembly_function(); 在C语言中声明汇编函数int main() {printf("Before calling the assembly function.\n");使用内联汇编调用汇编函数__asm__("call assembly_function;");printf("After calling the assembly function.\n");return 0;}在上面的示例中,我们使用`extern`关键字在C语言中声明了一个名为`assembly_function`的汇编函数。

然后,使用`__asm__`关键字将汇编代码嵌入到C语言程序的特定位置。

2. 使用外部汇编文件另一种调用汇编函数的方法是使用外部汇编文件。

我们可以编写一个独立的汇编文件,并在C语言程序中引用该文件。

下面是一个使用外部汇编文件调用汇编函数的示例:在`assembly_function.asm`文件中编写如下代码:assembly; assembly_function.asmsection .textglobal _start_start:; 汇编函数的实现; ...mov eax, 1 ; 返回值为1mov ebx, 0int 0x80 ; 调用系统调用在C语言程序中调用该汇编函数:c#include <stdio.h>extern void assembly_function(); 在C语言中声明汇编函数int main() {printf("Before calling the assembly function.\n");使用外部汇编文件调用汇编函数assembly_function();printf("After calling the assembly function.\n");return 0;}在上面的示例中,我们在C语言程序中使用`extern`关键字声明了一个名为`assembly_function`的汇编函数,并在汇编文件中实现了这个函数。

汇编-串操作指令

汇编-串操作指令

汇编-串操作指令串传输指令基础知识简介1. 系统标志寄存器EFLAGSDF: ⽅向标志位。

在串处理指令中,控制每次操作后si, di的增减DF=0 每次操作后si,di递增DF=1 每次操作后si,di递减2. std指令功能将系统标志寄存器EFLAGS中的DF(⽅向标志)置为1,即 DF=13. cld指令功能将系统标志寄存器EFLAGS中的DF(⽅向标志)置为0,即 DF=04. movs:串传送指令语法格式:movsb、movsw说明:(1)将DS:[SI]的内容传送到ES:[DI](2)若DF=0,则DI增加1,2、4。

否则DI减少1,2、45. stos:串存储指令语法格式:stosb、stosw、stosd说明:(1)将AL\AX\EAX寄存器的值复制到ES:DI所指的内存单元(2)若DF=0,则DI增加1,2、4。

否则DI减少1,2、46. scas:串扫描指令语法格式:scasb、scasw说明:(1)将ES:[DI]所指向的内容与AL/AX/EAX(字节/字/双字)进⾏⽐较,并依据所得到的差值来设置相关标志位。

受影响的标志位: AF,CF,OF,PF,SF,ZF(2)若DF=0,则DI增加1,2、4。

否则DI减少1,2、47. rep:重复前缀指令rep指令重复其后指定的字符串操作指令,重复的次数由计数寄存器cx来决定8. 使⽤串相关指令的⽅法:(1)传送的原始位置:ds:si(2)传送的⽬的位置:es:di(3)传送的⽅向:DF(4)传送长度:cx9. 算数和逻辑操作地址10. ⽰例如下:(1)#define copy_page(from,to) \__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024)) // 从from处复制1页内存到to处(4K字节)(2)unsigned long get_free_page(void){register unsigned long __res asm("ax");__asm__("std ; repne ; scasb\n\t" // 置⽅向位,al(0)与对应每个页⾯的(di)内容⽐较"jne 1f\n\t" // 如果没有等于0的字节,则跳转结束(返回0)."movb $1,1(%%edi)\n\t" // 1 => [1+edi],将对应页⾯内存映像bit位置1."sall $12,%%ecx\n\t" // 页⾯数*4k = 相对页⾯其实地址"addl %2,%%ecx\n\t" // 再加上低端内存地址,得页⾯实际物理起始地址"movl %%ecx,%%edx\n\t" // 将页⾯实际其实地址->edx寄存器。

汇编第3章 数据传送与算术运算指令

汇编第3章 数据传送与算术运算指令

DIV、IDIV
十进制调整指令 DAA、DAS、
1、 加法指令
加法指令: ADD
执行操作:
DST 不能是立即数和CS段寄 存器, DST、SRC都不能为 段寄存器,也不能同时为存储 器寻址。
DST, SRC
进位标志位 (0/1)
(DST) (SRC) + (DST)
带进位加法指令: ADC DST, SRC 执行操作: (DST) (SRC) + (DST) + CF
(2)传送偏移地址及数据段首址指令LDS
格式:LDS reg,mem MOV BX, OFFSET [BX+SI] × × 功能:将由源操作数确定的双字存储单元的内容传送给DS及目的 注意: OFFSET 只能与简单的符号地址相连。 操作数指定的 16 位通用寄存器中,其中高字单元的内容送给 DS,低 字单元的内容送给reg。
格式:LEA reg,mem 功能:将源操作数的有效地址EA传送给指定的通用寄存器。 MOV BX, OFFSET LIST ;功能与LEA相同 说明: ① 源操作数必须采用存储器寻址方式;目的操作数必须是一个 16 位或32位通用寄存器,但不能使用段寄存器。 LEA BX, [BX+SI] ;取基址变址寻址的有效地址给BX ② 本指令对标志位无影响。
BL ;商(AL)=05H=5D,余数(AH)=7CH=124D
【例3.9】写出实现有符号数0400H /0B4H运算的程序段。
MOV
MOV IDIV
AX,0400H
BL,0B4H BL
;(AX)=0400H=+1024D
;(BL)=0B4H=-76D
;(AL)=0F3H=-13D,(AH)=24H=36D

汇编 参数类型

汇编 参数类型

汇编参数类型Understanding parameter types in assembly language can be crucial for writing efficient and effective code. In assembly language, parameter types refer to the different data types that can be passed to a subroutine or function. These data types can include integers, floating-point numbers, strings, and more. By understanding the different parameter types, a programmer can ensure that the correct data is passed to a function, which can help avoid errors and improve the overall performance of the code.在汇编语言中,参数类型的理解对于编写高效和有效的代码至关重要。

在汇编语言中,参数类型是指可以传递给子例程或函数的不同数据类型。

这些数据类型可以包括整数、浮点数、字符串等。

通过理解不同的参数类型,程序员可以确保将正确的数据传递给函数,从而可以避免错误并提高代码的整体性能。

One common parameter type in assembly language is the integer, which is used to represent whole numbers. Integers can be signed or unsigned, which affects the range of values that can be stored. Signed integers can represent both positive and negative numbers,while unsigned integers can only represent non-negative numbers. By understanding the differences between signed and unsigned integers, a programmer can choose the appropriate type based on the requirements of the function or subroutine.汇编语言中的一种常见参数类型是整数,用于表示整数。

arm汇编语言调用C函数之参数传递

arm汇编语言调用C函数之参数传递

arm汇编语言调用C函数之参数传递于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS 主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。

这篇文档要讲的是汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回。

不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。

我们先讨论一下形参个数为4的情况.实例1:test_asm_args.asm//--------------------------------------------------------------------------------IMPORT test_c_args ;声明test_c_args函数AREA TEST_ASM, CODE, READONLYEXPORT test_asm_argstest_asm_argsSTR lr, [sp, #-4]! ;保存当前lrldr r0,=0x10 ;参数 1ldr r1,=0x20 ;参数 2ldr r2,=0x30 ;参数 3ldr r3,=0x40 ;参数 4bl test_c_args ;调用C函数LDR pc, [sp], #4 ;将lr装进pc(返回main函数)ENDtest_c_args.c//--------------------------------------------------------------------------------void test_c_args(int a,int b,int c,int d){printk("test_c_args:\n");printk("%0x %0x %0x %0x\n",a,b,c,d);}main.c//--------------------------------------------------------------------------------int main(){test_asm_args();for(;;);}程序从main函数开始执行,main调用了test_asm_args,test_asm_args 调用了test_c_args,最后从test_asm_args返回main。

汇编之函数堆栈传参

汇编之函数堆栈传参

汇编之函数堆栈传参
1.函数:
函数就是⼀系列指令的集合,为了完成某个会重复使⽤的特定功能。

⽐如:MOV EAX,1 MOV ECX,1 就相当于⼀个函数(指令的集合)
2.函数的调⽤:
(1)使⽤JMP来执⾏函数
使⽤JMP执⾏函数的话,JMP跳转到相应的指令后指令指针不再返回到原来位置的下⼀位:
(2)使⽤CALL来执⾏函数
以四条指令向普通寄存器存储值为例:
CALL执⾏前:
CALL执⾏后(F8):
可以看到CALL指令把当前指令的下⼀条指令推⼊栈中,在执⾏完四条指令后,RETN回到了当前指令的下⼀条指令。

执⾏顺序并没有改变。

3.参数、返回值
汇编中EAX通常⽤来存储函数的返回值的。

实现⼀个简单的加法函数:
⽅法如下:
(1)定义三条指令:
将ECX,EDX中的值相加;(参数)
将相加的值放到EAX中;
返回
(2)调⽤函数:
先向ECX,EDX中存⼊要加的两个数;
使⽤CALL调⽤对应⽅法;
F8逐步执⾏结果:
EAX中存储的就是相加的结果
3.堆栈传参
当参数过多,寄存器不够⽤可以使⽤堆栈传参:以⼀个累加的函数为例:
(1)再CALL函数之前,先向堆栈中push5个数:
(2)执⾏前先将EAX中的值清零
(3)F7逐步执⾏结果:。

深入理解计算机系统(3.3)---数据传送(或者说复制)指令详解

深入理解计算机系统(3.3)---数据传送(或者说复制)指令详解

深⼊理解计算机系统(3.3)---数据传送(或者说复制)指令详解引⾔ 上⼀章我们已经介绍了汇编语⾔的基础部分,包括数据格式、寄存器以及操作数的标识⽅式,接下来我们就应该去认识⼀下汇编语⾔当中的各个指令了。

这些指令⼤多数都⾮常简单,但是组合在⼀起却能模拟出我们程序当中想要的任何效果,确实是⼗分神奇的⼀件事。

数据传送指令 数据传送指令的⽬的是为了将⼀个数据从⼀个位置复制到另外⼀个位置。

既然如此,那么数据传送指令就会包含⼀个源操作数和⼀个⽬的操作数,指令会将原操作数的值复制到⽬的操作数并覆盖。

数据传送指令⼀共可分为五种,分别是mov、movs、movz、push以及pop,下⾯LZ依次介绍⼀下这五个指令的作⽤。

mov指令 mov指令的作⽤是将源操作数S中的数据复制到⽬的操作数D中,mov指令有⼀个数据格式和两个操作数,因此⼀般的形式为[movx S D]。

其中x为数据格式,S为源操作数,D为⽬的操作数。

这⾥举⼀个简单的例⼦,⽐如我们有⼀条指令为movl %edx %eax。

那么它的执⾏过程就如下图所⽰。

可以看到,在指令执⾏之后,%edx寄存器当中的内容会被复制到%eax寄存器。

需要⼀提的是,mov指令可以在后⾯加上任何数据格式,⽐如上⾯这⼀过程中,数据格式则为四个字节,也就是双字。

因此不难推断出,我们还可以使⽤movb和movw去复制⼀个字节或者两个字节。

movs指令 movs指令的作⽤是将源操作数S中的数据做符号扩展后,再复制到⽬的操作数D中,movs指令有两个数据格式和两个操作数,因此⼀般的形式为[movsxy S D]。

其中x、y为数据格式,S为源操作数,D为⽬的操作数。

其中x、y的组合⼀共有三种,分别是bw、bl、wl,这三个组合代表的意思分别是单字节到双字节,单字节到双字以及双字节到双字。

这⾥LZ依然举⼀个例⼦,对于指令movswl %dx %eax来讲,它的作⽤如下图所⽰。

这⾥为了可以看出符号位的扩展,因此LZ这⾥使⽤了⼗六进制的整数表⽰⽅式。

实验八 主程序与子程序之间的参数传递实验

实验八  主程序与子程序之间的参数传递实验

数学与软件科学学院实验报告学期:___2011__至____2011 第____2___ 学期 2011年4月22日课程名称:汇编语言专业:__信息与计算科学_________2008__级_6___班实验编号: 8 实验项目__主程序与子程序之间的参数传递实验指导教师_冯山姓名:尹洁学号: 2008060646 __实验成绩:_____一.实验目的:熟悉主程序和子程序之间的参数传递基本途径和方法。

二.实验内容:主要实验实例:(1) 把一个大写字母改写为小写字母的子程序的编写和调试。

(2) 写一个判别字符是否为数字的子程序,并利用该子程序删除一个字符串中的所有数字字符。

三.实验准备:有关子程序和主程序概念,及其参数传递方法。

四.实验步骤:(1) 把一个大写字母改写为小写字母的子程序的编写和调试。

在汇编语言中,要实现大小写字母的转换,我们得先分析一下大写字母和小写字母的ASCII码,通过比较可以发现,大写字母和小写字母之间二进制的区别就是第6位1还是0,如果是大写字母第6位为0,如果是小写字母,第6位则为1,举个例子:A的二进制表示为:0100 0001,a的二进制表示为:0110 0001,通过对比可以发现,它们的区别就是第六位是一还是0。

大写字母的第六位为0,小写字母的第六位为1。

知道这个就好办了:如果要转换成大写字母,则使用and指令把ASCII码的第6位置0;and al,11011111B如果要转换成小写字母,则使用or指令把ASCII码的第6为置1。

or al,00100000B。

程序代码:assume cs:codesg,ds:datasg,ss:stacksgdatasg segmentdb 'abc 'db 'lib 'db 'dos 'datasg endsstacksg segmentdw 0,0,0,0,0,0,0,0 ;定义一个段,用来做栈段,容量为16个字节stacksg endscodesg segmentstart:mov ax,stacksgmov ss,axmov sp,16mov ax,datasgmov ds,axmov bx,0mov cx,3 ;外层循环三次,对应为数据段中的三个字符串s0: push cx ;将外层循环的cx值压栈保存mov si,0mov cx,3 ;内层循环三次,对应为数据段中给出的每个字符串的三个字母s: mov al,[bx+si] ;and al,11011111b ;使用and把小谢字母转换为大写字母mov [bx+si],al ;重新保存到内存单元中inc si ;si加1,继续循环修改下一个字母loop sadd bx,16 ;把bx加上16指向下一个字符串所在的地址pop cx ;从栈顶弹出原来的cx值,恢复cxloop s0mov ax,4c00hint 21hcodesg endsend start运行结果:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档