汇编语言参数传递共28页

合集下载

C和汇编之间参数传递机制剖析

C和汇编之间参数传递机制剖析

C和汇编之间参数传递机制剖析作者:庞新法来源:《价值工程》2014年第29期摘要:本文剖析了混合编程转返机制和参数传递的基本方法。

Abstract: This paper illustrates the mixed programming turn back mechanism and basic methods of parameter transferring.关键词: C 语言;汇编语言;参数传递Key words: C language;assembly language;parameter transferring中图分类号:TP312 文献标识码:A 文章编号:1006-4311(2014)29-0225-021 绪论C语言与汇编语言混合编程,可以发挥各自优势,提高程序的开发效率。

这必然涉及到二者相互调用时的接口:C程序与汇编程序如何转返、二者之间如何互传数据。

2 名字声明约定2.1 汇编、C模块对自己未定义的但要引用的别的模块的名字(该名字允许被引用)要声明。

C模块声明格式:函数声明格式:extern类型函数名(形参表);变声明格式: Extern类型变量;汇编模块声明格式:函数声明格式:extern函数名:属性(near,far)。

变声明格式:Extern变量名:属性(byte,word,dword等)。

2.2 自己定义的不仅自己可用,且可供别的模块引用的名字也必须声明。

汇编模块声明格式:PUBLIC名字。

C模块声明格式:全局变量,函数名前不加static即可。

3 转返机制为了说明C主程序如何转到汇编子程序,汇编子程序执行结束如何返回C主程序,把例1 x1.c C程序翻译成汇编程序x1.asm,命令行键入命令TCC-S x1即可。

例1 /*x1.c*/extern int f2(int,int,int);main(){int a;a=f2(1,2,3);a=a+10;}上述程序经编译后,汇编程序如下(无关内容省去)/*x1.asm*/_TEXT segment byte public 'CODE'_main proc near ;小模式,类型为near,名字main编译后变为内部名(前加下划线) push si ;保护simov ax,3push ax ;实参3压栈mov ax,2push ax ;实参2压栈mov ax,1push ax ;实参1压栈call near ptr _f2 ;转入子程序add sp,6 ;丢弃栈中三个实参,确保实参不变mov si,ax ;出口参数固定是ax,从ax取结果mov ax,si ;机械性翻译,效率低,人工汇编编程,两个mov可不要add ax,10mov si,ax ;出口参数固定是ax,main加工结果送到约定寄存器ax@1:pop si ;恢复siret ;main子程序返回_main endp_TEXT endsPC机的堆栈是由高向低发展,压栈操作,栈中内容增多,SP值减小,反之出栈操作,栈中内容减少,SP值增大。

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

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

一、数据传输指令───────────────────────────────────────它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.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 //无进位转移。

编译原理期末复习题

编译原理期末复习题

编译原理期末复习题(包含上一份N多答案)(总28页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--编译原理复习题一、填空题:1、编译方式与解释方式的根本区别在于(是否生成目标代码)。

2、对编译程序而言,输入数据是(源程序),输出结果是(目标程序)。

3、如果编译程序生成的目标程序是机器代码程序,则源程序的执行分为两大阶段:(编译阶段)和(运行阶段)。

4、如果编译程序生成的目标程序是汇编语言程序,则源程序的执行分成三个阶段:(编译阶段)、(汇编阶段)和(运行阶段)。

5、自顶向下语法分析方法会遇到的主要问题有(回溯)和((左递归带来的)无限循环)。

6、LL(k)分析法中,第一个L的含义是(从左到右进行分析),第二个L的含义是(每次进行最左推导),“k”的含义是(向输入串中查看K个输入符号)。

7、LL(1)分析法中,第一个L的含义是(从左到右进行分析),第二个L的含义是(每次进行最左推导),“1”的含义是(向输入串中查看1个输入符号)。

8、自顶向下语法分析方法的基本思想是:从(识别符号)出发,不断建立(直接推导),试图构造一个推导序列,最终由它推导出与输入符号相同的(符号串)。

9、自底向上语法分析方法的基本思想是:从待输入的符号串开始,利用文法的规则步步向上进行(直接归约),试图(归约)到文法的(识别符号|开始符号)。

10、LR(0)分析法的名字中,“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“0”的含义是(向貌似句柄的符号串后查看0个输入符号)。

11、LR(1)分析法的名字中,“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“1”的含义是(向貌似句柄的符号串后查看1个输入符号)。

12、SLR(1)分析法的名字中,“S”的含义是(简单的),“L”的含义是(从左到右进行分析),“R”的含义是(采用最右推导的逆过程---最左归约),“1”的含义是(向貌似句柄的符号串后查看1个输入符号)。

7.3 子程序的参数传递

7.3 子程序的参数传递
解:
;子程序功能:把寄存器BX的内容按十进制有符号数显示出来
;入口参数:BX
;出口参数:无,只有显示信息
;算法描述:1、定义6个字节的存储单元
2、先判断BX是否小于零,如果是,则先显示负号'-',再取BX的绝对值;
3、采用除10,得余数的ຫໍສະໝຸດ 法,从低位向高位求出每位十进制位;
4、输出数据的字符串。
7.3 子程序的参数传递
子程序一般都是完成某种特定功能的程序段。当一个程序调用一个子程序时,通常都向子程序传递若干个数据让它来处理;当子程序处理完后,一般也向调用它的程序传递处理结果,我们称这种在调用程序和子程序之间的信息传递为参数传递。
用程序向子程序传递的参数称为子程序的入口参数,子程序向调用它的程序传递的参数称为子程序的出口参数。子程序的入口参数和出口参数都是任意项,对某个具体的子程序来说,要根据具体情况来确定其入口和出口参数,也可以二者都没有。

MOVAL, 'b'
CALLUPPER;子返回时,(AL)='B'

MOVAL, '2'
CALLUPPER;子返回时,AL的值不变,因为'2'不是字母

例7.3 按五位十进制的形式显示寄存器BX中的内容,如果BX的值小于0,则应在显示数值之前显示负号'-'。
例如:(BX)=123,显示:00123;(BX)=-234,显示:-00234;
SubDataSEGMENT
DB 5 DUP('0'), 0ah, 0dh, '$' ;0ah、0dh:换行、回车

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和重⼊。

数据传送指令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以后的范围内。

子程序的参数传递

子程序的参数传递

⼦程序⼀般都是完成某种特定功能的程序段。

当⼀个程序调⽤⼀个⼦程序时,通常都向⼦程序传递若⼲个数据让它来处理;当⼦程序处理完后,⼀般也向调⽤它的程序传递处理结果,我们称这种在调⽤程序和⼦程序之间的信息传递为参数传递。

⽤程序向⼦程序传递的参数称为⼦程序的⼊⼝参数,⼦程序向调⽤它的程序传递的参数称为⼦程序的出⼝参数。

⼦程序的⼊⼝参数和出⼝参数都是任意项,对某个具体的⼦程序来说,要根据具体情况来确定其⼊⼝和出⼝参数,也可以⼆者都没有。

程序和被调⽤⼦程序之间的参数传递⽅法是程序员⾃⼰或和别⼈事先约定好的信息传递⽅法。

这种信息传递⽅法可以是多种多样的,在本节,我们只介绍常⽤的、⾏之有效的参数传递⽅法有:寄存器传递参数、约定存储单元传递参数和堆栈传递参数等。

如果对其它的参数传递⽅法感兴趣的话,可参考其它《汇编语⾔程序设计》书籍。

7.3.1 寄存器传递参数 ⼀⽅⾯,由于CPU中的寄存器在任何程序中都是“可见”的,⼀个程序对某寄存器赋值后,在另⼀个程序中就能直接使⽤,所以,⽤寄存器来传递参数最直接、简便,也是最常⽤的参数传递⽅式。

但另⼀⽅⾯,CPU中寄存器的个数和容量都是⾮常有限,所以,该⽅法适⽤于传递较少的参数信息。

例7.1是⽤寄存器传递参数的例⼦,⼦程序处理的数据被保存在寄存器AL中。

假设有下列的程序段: … MOVAL, ’b’ CALLUPPER;⼦返回时,(AL)=’B’ … MOVAL, ’2’ CALLUPPER;⼦返回时,AL的值不变,因为’2’不是字母 … 例7.3 按五位⼗进制的形式显⽰寄存器BX中的内容,如果BX的值⼩于0,则应在显⽰数值之前显⽰负号’-’。

例如:(BX)=123,显⽰:00123;(BX)=-234,显⽰:-00234; 解: ;⼦程序功能:把寄存器BX的内容按⼗进制有符号数显⽰出来 ;⼊⼝参数:BX ;出⼝参数:⽆,只有显⽰信息;算法描述: 1、定义6个字节的存储单元 2、先判断BX是否⼩于零,如果是,则先显⽰负号’-’,再取BX的绝对值; 3、采⽤除10,得余数的⽅法,从低位向⾼位求出每位⼗进制位; 4、输出数据的字符串。

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.操作数传送指令:-MOV:将数据从一个位置复制到另一个位置。

-XCHG:交换两个位置中的数据。

2.算术指令:-ADD:将两个数相加并将和存储在指定位置。

-SUB:将两个数相减并将差存储在指定位置。

-MUL:将两个数相乘并将结果存储在指定位置。

-DIV:将两个数相除并将商存储在指定位置。

-INC:将一个数增加1-DEC:将一个数减少13.逻辑指令:-AND:对两个数进行逻辑与操作并将结果存储在指定位置。

-OR:对两个数进行逻辑或操作并将结果存储在指定位置。

-XOR:对两个数进行逻辑异或操作并将结果存储在指定位置。

-NOT:对一个数进行逻辑非操作并将结果存储在指定位置。

4.控制指令:-JMP:无条件跳转到指定位置。

-JZ:如果前一条指令的结果为0,则跳转到指定位置。

-JNZ:如果前一条指令的结果不为0,则跳转到指定位置。

-JC:如果前一条指令产生进位,则跳转到指定位置。

-JNC:如果前一条指令不产生进位,则跳转到指定位置。

5.栈操作指令:-PUSH:将数据放入栈中。

-POP:将栈顶的数据弹出。

6.输入输出指令:-IN:从外部设备中读取数据。

-OUT:将数据发送到外部设备。

7.循环指令:-LOOP:根据计数寄存器的值,重复执行指定的代码块。

8.过程调用指令:-CALL:调用一个子程序。

-RET:从子程序返回。

9.字符串指令:-MOVS:将一个字节或一个字从一个位置复制到另一个位置。

-CMPS:将两个位置中的字节或字进行比较。

除了以上提到的指令外,不同的汇编语言还有其它特定的指令,用于特定的硬件操作或功能实现。

这些指令的语法与使用方法可能略有不同,具体请参考所使用的汇编语言的文档或手册。

总之,汇编语言指令是汇编语言的基础,熟练掌握和理解这些指令对于编写高效和可靠的汇编程序至关重要。

汇编语言第5章王爽版(子程序调用指令)

汇编语言第5章王爽版(子程序调用指令)
二、主程序与过程的参数传递方式
例5-1:分别用三种参数传递方法编写求1+2的和的程序。要求将结果送到内存单元,并显示。
DATA SEGMENT SUM DB 0 DATA ENDS STACK SEGMENT DB 100 DUP(?) STACK ENDS CODE SEGMENT ASSUME DS:DATA,SS:STACK,CS:CODE START: MOV AX,DATA MOV DS,AX MOV AL, 1 MOV BL, 2 CALL subprog mov ah,4cH int 21h CODE ENDS END START
5.2 子程序的定义、调用和返回(续)
子程序返回指令(RET)
RET [n] 功能:弹出CALL指令压入堆栈的返回地址 段内返回——偏移地址IP出栈 IP←SS:[SP], SP+2 段间返回——偏移地址IP和段地址CS出栈 IP←SS:[SP],SP←SP+2 CS←SS:[SP],SP←SP+2
子程序的概念
子程序的现场保护与参数传递**
子程序的嵌套与递归调用
子程序的定义、调用和返回 **
子程序设计 *
宏汇编程序设计
教学基本内容
第5章 结构化程序设计
子程序:在程序设计中,我们会发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。 过程(子程序):是指功能相对独立的一段程序。 主程序和子程序间的关系:调用子程序的程序称为主调程序或主程序,被调用的程序称为子程序。
Spr PROC PUSH BP MOV BP, SP MOV AX, [BP+6] MOV BX, [BP+4] ADD AL, BL OR AL, 30H MOV DL,AL MOV AH,2 INT 21H MOV SUM, AL POP BP RET Spr ENDP

汇编第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

子程序的参数传递

子程序的参数传递

子程序的参数传递在编程中,子程序是一种被设计为完成特定任务的独立部分。

子程序可以是函数、过程或方法,在不同编程语言中可能有不同的术语。

子程序通过参数传递来接收输入值,并通过返回值来提供输出结果。

参数传递是将数据从一个程序的一部分传递到另一部分的过程。

它允许子程序在执行时获得所需的输入,并且可以改变或返回一些结果。

参数传递的方法包括传值、传引用和传地址。

每种方法都有其特定的优势和用途。

传值是将参数的值复制到子程序的局部变量中。

这意味着子程序在执行时修改参数的值不会影响到调用程序中的原始值。

传值适用于那些不需要修改参数值的情况。

例如,一个计算两个数字之和的函数可以使用传值方式,因为它只是需要读取输入参数的值而不改变它们。

传引用是将参数的内存地址传递给子程序。

这样,子程序可以通过地址访问到调用程序中的变量,并修改其值。

传引用适用于需要修改参数值的情况。

例如,一个交换两个数值的函数可以使用传引用方式,因为它需要交换调用程序中的原始变量的值。

传地址是一种特殊的传引用方法,它将参数的地址作为指针传递给子程序。

这样,子程序可以通过指针访问和修改调用程序中的变量。

传地址适用于需要传递数据结构或数组的情况。

例如,一个函数可以使用传地址方式将一个数组的元素逐一修改为一些特定值。

在使用参数传递时,开发人员应该注意一些潜在的问题。

首先,如果传递的是大型数据结构或数组,那么传值的方式可能会引起性能问题,因为它需要复制整个数据结构。

在这种情况下,传地址或传引用的方式更加高效。

其次,传引用和传地址可能导致意外的结果,因为它们直接修改原始变量的值。

如果不小心处理传引用或传地址的参数,在子程序中对它们进行的操作可能会影响到调用程序中的其他代码。

因此,在使用这些方法时,需要特别谨慎地处理参数的值。

另外,对于一些特殊的情况,可以使用返回值的方式来传递结果。

这意味着子程序通过返回一个值来提供输出结果,而不需要直接修改参数。

返回值适用于需要返回单个结果的情况,例如计算两个数字之和的函数。

C 和汇编之间参数传递机制剖析

C 和汇编之间参数传递机制剖析

C 和汇编之间参数传递机制剖析发表时间:2014-12-09T13:26:56.623Z 来源:《价值工程》2014年第10月中旬供稿作者:庞新法[导读] C 语言与汇编语言混合编程,可以发挥各自优势,提高程序的开发效率。

庞新法PANG Xin-fa(陕西省委党校科技教研部,西安710061)(Technology Research Department,Shaanxi Province Party School of the CPC,Xi'an 710061,China)摘要:本文剖析了混合编程转返机制和参数传递的基本方法。

Abstract: This paper illustrates the mixed programming turn back mechanism and basic methods of parameter transferring.关键词:C 语言;汇编语言;参数传递Key words: C language;assembly language;parameter transferring中图分类号院TP312 文献标识码院A 文章编号院1006-4311(2014)29-0225-021 绪论C 语言与汇编语言混合编程,可以发挥各自优势,提高程序的开发效率。

这必然涉及到二者相互调用时的接口:C 程序与汇编程序如何转返、二者之间如何互传数据。

2 名字声明约定2.1 汇编、C 模块对自己未定义的但要引用的别的模块的名字(该名字允许被引用)要声明。

C 模块声明格式:函数声明格式:extern 类型函数名(形参表);变声明格式:Extern 类型变量;汇编模块声明格式:函数声明格式:extern 函数名:属性(near,far)。

变声明格式:Extern 变量名:属性(byte,word,dword 等)。

2.2 自己定义的不仅自己可用,且可供别的模块引用的名字也必须声明。

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

13、遵守纪律的风气的培养,只有领 导者本 身在这 方面以 身作则 才能收 到成效 。—— 马卡连 柯 14、劳动者的组织性、纪律性、坚毅 精神以 及同全 世界劳 动者的 团结一 致,是 取得最 后胜利 的保证 。—— 列宁 摘自名言网
15、机会是不守纪律的。——雨果
31、只有永远躺在泥坑里的人,才不会再掉进坑里。——黑格尔 32、希望的灯一旦熄灭,生活刹那间变成了一片黑暗。——普列姆昌德 33、希望是人生的乳母。——科策布 34、形成天才的决定因素应该是勤奋。——郭沫若 35、学到很多东西的诀窍,就是一下子不要学很多。——洛克
汇编语言参数传递
11、战争满足了或曾经满足过人的 好斗的 本能, 但它同 时还满 足了人 对掠夺 ,破坏 以及残 酷的纪 律和专 制力的 欲望。 ——查·埃利奥 特 12、不应把纪律仅仅看成教育的手段 。纪律 是教育 过程的 结果, 首先是 学生集 体表现 在一切 生活领 域—— 生产、 日常生 活、学 校、文 化等领 域中努 力的结 果。— —马卡 连柯(名 言网)
相关文档
最新文档