;注解: laogu http://www.laogu.com ;这是一段在80x86里的汇编源程序,用来生成多播地址过滤的 MAR0-MAR7(以太网卡里的多播地址过滤寄存器) ;多播也叫组播。程序调用的时候 将组播地址列表的地址传递到ds:si , ;列表相当于c语言里的二维数组 unsigned char multicast_addresses[ax][6]; ; 因为每个地址的长度为6,总共有ax个组播地址。 ; ds:si 相当于c语言里的指针 unsigned char *multicast_addresses ; ;将地址总数传递到ax,字节数(=地址总数*6)传递到 cx里(在这个程序里,没有用到cx传递的值) ;程序运算的结果放在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