;程序运算的结果放在mcast_list_bits里,相当于c语言里的unsigned char mcast_list_bits[8];
;程序里的di相当于c语言里的指针 unsigned char *mcast_list_bits;
;mcast_list_bits[8]对应于地址过滤寄存器MAR[8],即MAR0---MAR7
;函数 set_hw_multi ; Set the multicast mask bits in chip是将mcast_list_bits[8]写入到MAR0--MAR7
;的一个函数调用,这里没有写。
public set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
; cx = number of bytes.
;入口调用: 将list of multicast addresses 组播地址列表(可以有多个组播地址)的地址放在
;ds:si 指针里。ax为多播地址的个数。cx为字节数
;return nc if we set all of them, or cy,dh=error if we didn't.
;设置成功返回c=0,失败c=1(c就是cy,cpu标志位)
assume ds:code
mov cx,ax ;keep a count of addresses in cx.
;cx=多播地址的个数
mov di,offset mcast_list_bits ;di=64位的多播地址crc
xor ax,ax
mov [di+0],ax
mov [di+2],ax
mov [di+4],ax
mov [di+6],ax ;将多播地址8个字节的crc全部设置为0
jcxz set_mcl_2 ;cx=0 跳到set_mc1_2,将多播地址crc设置为全部0
set_mcl_1:
call add_mc_bits ;调用crc计算
loop set_mcl_1
set_mcl_2:
call set_hw_multi ; Set the multicast mask bits in chip
;将mcast_list_bits[8] 8个字节分别写入到MAR0--MAR7
;mcast_list_bits[0]对应于MAR0 .
clc
ret
;=================
add_mc_bits: 开始计算
;entry: ds:si -> multicast address, di-> sixty-four bit multicast filter.
;preserve cx, di, increment si by EADDR_LEN
push cx ;保存cx,就是保存多播地址的个数
mov cx,EADDR_LEN ;EADDR_LEN就是以太网地址的长度=6
mov dx,0ffffh ; this is msw.
mov bx,0ffffh ; set 32 bit number
add_mcb_1:
lodsb ;将一个字节的数(地址为si指向的数)装到AL里,同时使si地址+1
call upd_crc ; update crc
loop add_mcb_1 ; and loop.
;=============
ifdef MULTICRC_REVERSE ;ifdef 到endif这段函数是产生CRC过滤的反顺序码的,
;例如 0000001 反顺序就是 1000000
;就是高位和低位反过来。
;程序的执行将dh里的数反顺序排列
;这段程序应该是没有使用,也就是说我们用的是正顺序码。而不是反顺序码。
mov cl,8
add_mcb_2:
shl dh,1 ;逻辑左移1位,高位进c,地位补0
rcr dl,1 ;带进位的循环右移,c进高位,低位进c
loop add_mcb_2
mov dh,dl
endif
;====================
mov al,dh ; get ms 8 bits,
rol al,1 ;循环左移,高位进c和低位,
rol al,1
rol al,1 ; put 3 bits at bottom
and al,7
mov bl,al ; save in bl
xor bh,bh ; make bx into an index to the byte.
mov al,dh ; get ms 8 bits,
ror al,1 ;循环右移,低位进c和高位
ror al,1 ; but at bottom
and al,7
mov cl,al ; save in cl
mov al,1
shl al,cl ; set the correct bit,
;逻辑左移1位,高位进c,地位补0
or [bx+di],al
pop cx
ret
;
; dx is high,
; bx is low.
; al is data
;======================
upd_crc:
push cx
mov cx,8 ; do 8 bits;cx=次数
mov ah,0
upd_crc1:
shl bx,1 ; shift bx ;bx在最开始时被设置为0xffff
;逻辑左移1位,高位进c,地位补0
rcl dx,1 ; through dx;dx最开始被设置为0xffff
;带进位循环左移,高位进c,c进低位
rcl ah,1 ; carry is at bottom of ah
;带进位循环左移,高位进c,c进低位
xor ah,al ; xor with lsb of data
;逻辑异或,结果放在左边的ah里,相同为0,不同为1
rcr ah,1 ; and put in carry bit
;带进位的循环右移,c进高位,低位进c
jnc upd_crc2
;
; autodin is x^32+x^26+x^23x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1
;
xor dx,0000010011000001b
xor bx,0001110110110110b + 1 ;plus one for end-around carry.
upd_crc2:
shr al,1 ; shift the data
; 循环右移,高位补0,低位进c
loop upd_crc1
pop cx
ret
以下是在keil c51里的c语言程序,为斑竹所写 [color="#ff33cc"]点击这里打开
。
//作者laogu http://www.laogu.com
//程序的功能是根据多播地址multicast_address[6]的值,计算出MAR0-MAR7,就是multicast_filter[8];
//本程序指计算一个多播地址。如果有多个多播地址,将每个多播地址生成的multicast_filter[8]相或就可以了,
//例如根据多播地址 01:00:5e:00:00:01生成的 value1=multicast_filter[8];
//根据多播地址 01:00:5e:00:00:02生成的 value2=multicast_filter[8];
//那么对这两个多播地址生成的multicast_filter[8]=value1 | value2 ;将两个值相或
//很容易从这里得到如果要接收所有多播地址的数据包,MAR0--MAR7必须设置为0xff,就是说
//multicast_filter[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
#define al ax_value.bytes.low
#define bl bx_value.bytes.low
#define cl cx_value.bytes.low
#define ah ax_value.bytes.high
#define bh bx_value.bytes.high
#define dh dx_value.bytes.high
#define ax ax_value.word
#define bx bx_value.word
#define cx cx_value.word
#define dx dx_value.word
#define shl_bx if((bx&0x8000)!=0){cf=1;}else{cf=0;};bx=bx>1;
#define rcl_dx if((dx&0x8000)!=0){cf_temp=1;}else{cf_temp=0;};dx=dx>1;if(cf){ah=ah+0x80;};cf=cf_temp;
#define rol_al if((al&0x80)!=0){cf=1;}else{cf=0;};al=al>1;if(cf){al=al+0x80;};
union u {unsigned int word;
struct{unsigned char high;unsigned char low;}bytes;//字节顺序为高位在前的2byte结构
};
union u ax_value;
union u bx_value;
union u cx_value;
union u dx_value;
bit cf;
bit cf_temp;
unsigned char multicast_address[6]={0x01,0x00,0x5e,0x00,0x00,0x00};
//unsigned char multicast_address[6]={0x00,0x00,0x00,0x5e,0x00,0x01}; //只计算一个多播地址
//unsigned char multicast_address[6]={0x01,0x80,0xc2,0x00,0x00,0x00};
unsigned char multicast_filter[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//结果放在这里,就是MAR0--MAR7的值
//;;0x41,0x00,0x00,0x80,0x00,0x00,0x00,0x00;
void up_crc(unsigned char al_byte)
{
al=al_byte;
ah=0;
for (cx=0;cxshr_al;
}