You are on page 1of 32

)

1) Conversion of Double BCD to Binary


: Double BCD (1-byte, dbcd_num) (1byte, binary_num). (Double BCD byte BCD nibbles
).
:
- uppernibble: nibble
R1:R0
.
debugging:
.

Start
uppernibble := dbcd_num & $F0
uppernibble >> 4

uppernibble < 10
?

No

Yes
uppernibble := uppernibble * 10
binary_num := dbcd_num & $0F

binary_num < 10
?

No

Yes
binary_num := binary_num + uppernibble

End

:
;-------------------- Double BCD to Binary -------------------;Title: CONV_DBCD_BIN
;Purpose: Conversion of a 1-byte double BCD number (a byte containing BCD digits in
;
both its nibbles) to a 1-byte Binary number
;Input Parameters:
;
dbcd_num: 1-byte double BCD number (a byte containing BCD digits in both its
;
nibbles) to be converted - stored in R16
;Other variables:
;
binary_num: 1-byte Binary number resulting from conversion (output parameter)
;
stored in R17
;
uppernibble: temp storage of upper nibble's binary equivalent - stored in R18
;"Special purpose" Registers used: R1:R0 for the multiplication result
;Exit: "binary_num" holds the binary equivalent of "dbcd_num"
;Errors: one of the BCD digits has ineligible value (is >1001) --> sets T flag
;Comments: ;-------------------.def dbcd_num=R16
.def binary_num=R17
.def uppernibble=R18
;---------CONV_DBCD_BIN:
mov uppernibble, dbcd_num
cbr uppernibble, $0F
(1)
swap uppernibble
cpi uppernibble, 10
brsh inel_bcd_digit
ldi binary_num, 10
(2)
mul uppernibble, binary_num ; upper nibble's binary equivalent is stored in R0
mov binary_num, dbcd_num
cbr binary_num, $F0
cpi binary_num, 10
brsh inel_bcd_digit
add binary_num, R0
clt
ret
inel_bcd_digit:
set
ret
;----- End of subroutine CONV_DBCD_BIN ----.undef dbcd_num
.undef binary_num
.undef uppernibble
:
(1) assembly andi uppernibble,
$F0 (
).
AVR ,
. assembly (
) .

(2) .

.

2) Conversion of ASCII Hex to Binary


: 2 ASCII bytes
(msaschex:lsaschex) (1-byte, binary_num).
debugging:

.

Start

Is msaschex >$2F
and <$3A?

No

Yes

No

Yes
lsaschex := lsaschex - $30

msaschex << 4
binary_num := msaschex & lsaschex

End

No

Yes

msaschex := msaschex - $30

Is lsaschex >$2F
and <$3A?

Is msaschex >$40
and <$47

msaschex := msaschex - $37

Is lsaschex >$40
and <$47

No

Yes
lsaschex := lsaschex - $37

:
;-------------------- ASCII Hex to Binary -------------------;Title: CONV_AHEX_BIN
;Purpose: Conversion of a 2 ASCII bytes Hexadecimal number to a 1-byte Binary number
;Input Parameters:
;
lsaschex: ASCII representation of the least significant Hexadecimal digit
;
stored in R16 - altered
;
msaschex: ASCII representation of the most significant Hexadecimal digit
;
stored in R17 - altered
;Other variables:
;
binary_num: 1-byte Binary number resulting from conversion (output parameter)
;
stored in R16
;Exit: "binary_num" holds the binary equivalent of $"msaschex:lsaschex"
;Errors: one of the Hexadecimal digits has ineligible value --> sets T flag
;
(eligible values are: $30-$39 AND $41-$46)
;Comments:
;
- Since the original value of "lsaschex" is altered, the Register that holds it
;
is also used for the "binary_num" variable
;-------------------.def lsaschex=R16
.def msaschex=R17
.def binary_num=R16
;---------CONV_AHEX_BIN:
cpi msaschex, $30
brlo inel_hex_digit
cpi msaschex, $3A
brsh tenorbigger_1
subi msaschex, $30
rjmp check_lsdigit
tenorbigger_1:
cpi msaschex, $41
brlo inel_hex_digit
cpi msaschex, $47
brsh inel_hex_digit
subi msaschex, $37
check_lsdigit:
cpi lsaschex, $30
brlo inel_hex_digit
cpi lsaschex, $3A
brsh tenorbigger_2
subi lsaschex, $30
rjmp combine
tenorbigger_2:
cpi lsaschex, $41
brlo inel_hex_digit
cpi lsaschex, $47
brsh inel_hex_digit
subi lsaschex, $37
combine:
swap msaschex
or binary_num, msaschex
; either OR or ADD have the same result
clt
ret

inel_hex_digit:
set
ret
;----- End of subroutine CONV_AHEX_BIN ----.undef lsaschex
.undef msaschex
.undef binary_num
:
,
ASCII .

3) Conversion of BCD to 7 segment LED display


: BCD (1-byte, dbcd_digit)
7 LED (1-byte, led7_code).
BCD 0 9, E. LED
pin 0.
R31:R30 .
debugging:
.

Start

bcd_digit < 10
?

No

Yes
Z := led7_table << 1
Z := Z + bcd_digit
led7_code := [Z]

End

led7_code := $30

:
;-------------------- BCD to 7 segment LED display -------------------;Title: CONV_BCD_LED7
;Purpose: Conversion of a 1-byte BCD digit to values that may be outputted to a 7
;
segment LED display for the BCD digit's depiction
;Input Parameters:
;
bcd_digit: 1-byte BCD digit to be depicted - stored in R16
;Other variables:
;
led7_code: the corresponding to "bcd_digit" value that may be outputted to a 7
;
segment LED display (output parameter) - stored in R17
;"Special purpose" Registers used: R31:R30 (Z) for reading from Program Memory
;Exit: "led7_code" holds the 7 segment LED display equivalent of "dbcd_digit"
;Errors:
;
- "dbcd_digit" has ineligible value (is >$09) --> "led7_code"=$30 (depicts 'E')
;Comments:
;
- LED segments are emitting light when the corresponding output pin's value is 0
;
- 7 segment LED code uses 7 bits (the MSb is not used - considered to be 0 in
;
the table's values) ordered in a byte as "_ABCDEFG", connected as following:
;
- A: the upper horizontal segment
_____
;
- B: the right upper segment
| A |
;
- C: the right lower segment
F|
|B
;
- D: the lower horizontal segment
|
|
;
- E: the left lower segment
| G |
;
- F: the left upper segment
E|
|C
;
- G: the middle horizontal segment
|
|
;-------------------D
.def bcd_digit=R16
.def led7_code=R17
led7_table:
.DB $01, $4F, $12, $06, $4C, $24, $60, $0F, $00, $0C
;---------CONV_BCD_LED7:
cpi bcd_digit, $10
brsh inel_bcd_byte
ldi ZL, LOW(led7_table)
ldi ZH, HIGH(led7_table)
lsl ZL
rol ZH
add ZL, bcd_digit
brcc no_carry
inc ZH
no_carry:
lpm led7_code, Z
ret
inel_bcd_byte:
ldi led7_code, $30
ret
;----- End of subroutine CONV_BCD_LED7 ----.undef bcd_digit
.undef led7_code
:

led bit ,

)
1) String concatenation
: ,
. (concat_len).
byte .
:
- temp1: ,

( ,
)
- temp2:

- temp_ad:
debugging:
(i) ?
(ii)
? ( 1-byte )
(iii)
, byte
? ( )
(iv) ? ( )

Start

(i) str2_length = 0 or
str1_length >= concat_length

Yes

End

No
new_length := str1_length + str2_length

(ii)

new_length >
concat_length ?

Yes

No
(iv)counter := new_length - str1_length
str2_ad := str2_ad + 1
(iii)
temp_ad := str1_ad + str1_length + 1

temp_char := [str2_ad]
[temp_ad] := temp_char
counter := counter - 1

No

counter = 0
?
Yes
End

new_length := concat_length
T := 1

:
;-------------------- String concatenation -------------------;Title: STR_CONCAT
;Purpose: Concatenation of two strings, by adding the one at the end of the other,
;
up to a given maximum concatenated string length - the first byte of strings
;
stores its length --> maximum string length=255
;Input Parameters:
;
concat_len: maximum length of the concatenated string - stored in R16
;
str1_stad: starting address of string 1 - stored in R27:R26 (X)
;
str2_stad: starting address of string 2 - stored in R29:R28 (Y) - altered
;Other variables:
;
temp1: temporary storage of str2_len, of str1_len after concatenation, and of
;
num of chars to be added - stored in R17
;
temp2: temporary storage of original str1_len and of char currently transferred
;
stored in R18
;
temp_ad: temporary address to which the copied chars as stored
;
(not necessary, it is employed in order to avoid altering "str1_stad")
;
stored in R31:R30 (Z)
;Exit: - (string 2 or part of it has been added at the end of string 1)
;Errors:
;
ErrorA: string1_length>=concat_length OR string2_length=0 (no changes)
;
--> sets both T and V flags
;
(inappropriate block bounds either for the old or the new location)
;
ErrorB: string1_length+string2_length>concat_length (only a part of string 2 is
;
added at the end of string 1) --> sets T flag, clears V flag
;Comments:
;
- There are no checks for "eligible" bounds of the strings with regard to the
;
allowable (in mega128, data should be stored between $100 and ($1100-a))
;
a: SRAM used locations (for the Stack or other data)
;
- "str2_stad" has been altered at the end of subroutine's code. If it needs to
;
remain unchanged, the "num of chars to be added" before starting adding them
;
(stored at "temp1" at that point) should be stored in an other Register; before
;
subroutine's end, the stored value incremented by 1 should be subtracted from
;
the modified "str2_stad".
;-------------------.def concat_len=R16
.def str1_stad_L=R26 ; XL
.def str1_stad_H=R27 ; XH
.def str2_stad_L=R28 ; YL
.def str2_stad_H=R29 ; YH
.def temp1=R17
.def temp2=R18
.def temp_ad_L=R30 ; ZL
.def temp_ad_H=R31 ; ZH
;---------STR_CONCAT:
ld temp1,
tst temp1
(i)
breq no_concat
ld temp2,
cp temp2, concat_len
(i)
brsh no_concat
clt
; in order to remember if errorB occured or not
add
temp1,
temp2
(iv)

(1) (ii)

brcs partial_concat
; string1_length+string2_length>255 --> >concat_len
cp concat_len, temp1
(ii)
brsh str1newlen_ok
partial_concat:
set
; mark ErrorB
(iv)
mov temp1, concat_len
(2) str1newlen_ok:
st X, temp1
sub temp1, temp2
; temp1 holds the num of chars to be added
movw temp_ad_L, str1_stad_L
(3)
adiw temp_ad_L, 1
; increment by one in order to skip the length's byte
adiw str2_stad_L, 1
add temp_ad_L, temp2
; move temp_ad at the end of string 1
brcc add_char
inc temp_ad_H
add_char:
ld temp2, Y+
(iii)
st Z+, temp2
dec temp1
brne add_char
clv
ret
no_concat:
set
sev
ret
;----- End of subroutine STR_CONCAT ----.undef concat_len
.undef str1_stad_L
.undef str1_stad_H
.undef str2_stad_L
.undef str2_stad_H
.undef temp1
.undef temp2
.undef temp_ad_L
.undef temp_ad_H
:
(1) (C=1)
.
(2)
. temp1 .
.
(3)
. ,

. (
)
16-bit , .
.

2) DESIGN NOTE #043 (www.avrfreaks.net)

3) Find the position of a substring in a string


: - (substring)
(index) . , 0.
byte .
:
- counter1: ( )
- counter2:
- ( )
- temp1_char:
- temp2_char: -
- temp_ad1:
- temp_ad2: -
debugging:
(i) -? (
)
(ii) ?
(iii)
-
? (
)

Start

(ii)
str1_length = 0 or
str1_length < str2_length or
str2_length = 0

Yes

End

No
(iii) counter1 := str1_length - str2_length
counter2 := str2_length
index := 1
temp1_ad := str1_ad + 1
temp2_ad := str2_ad + 1

temp1_char := [temp1_ad]
temp2_char := [temp2_ad]

temp1_char =
temp2_char ?
Yes
counter2 := counter2 - 1

temp1_ad := temp1_ad + 1
temp2_ad := temp2_ad +1

No

counter2 = 0
?
Yes
End

No

index := index + 1
temp1_ad := str1_ad + index
temp2_ad := str2_ad + 1
counter2 := str2_length
No
(i)
counter1 < 0
?
Yes

counter1 := counter1 - 1

:
;------------------ Find the position of a substring in a string -----------------;Title: SUBSTR_POS
;Purpose: Search for the first occurrence of a substring within a string and return
;
its starting index
;
! the first byte of strings stores its length --> maximum string length=255
;Input Parameters:
;
str1_stad: starting address of string - stored in R17:R16
;
str2_stad: starting address of substring - stored in R19:R18
;Other variables:
;
index: starting index of the first occurrence of the substring within the string
;
(output parameter) - stored in R20
;
counter1: counter of remaining "substring starts" within string - stored in R21
;
(outer loop counter, reduced by one each time the check starting address is
;
incremented by one)
;
counter2: counter of the chars remaining to be matched - stored in R22
;
(inner loop counter, set to substring_length each time the check starting
;
address is incremented by 1 --- when equal to 0 --> successful match)
;
temp1_char: char in string currently processed - stored in R23
;
temp2_char: char in substring currently processed - stored in R24
;
temp_ad1: address of the currently processes string's char
;
stored in R29:R28 (Y)
;
temp_ad2: address of the currently processes substring's char
;
stored in R31:R30 (Z)
;Exit: If the substring is found within the string, "index" holds the starting index
;
of the first occurrence of the substring within the string. Else "index"=0.
;Errors: string_length=0 OR substring_length=0 OR substring_length>string_length
;
--> sets T flag (inappropriate string length)
;Comments:
;
- There are no checks for "eligible" bounds of the strings with regard to the
;
allowable (in mega128, data should be stored between $100 and ($1100-a))
;
a: SRAM used locations (for the Stack or other data)
;-------------------.def str1_stad_L=R16
.def str1_stad_H=R17
.def str2_stad_L=R18
.def str2_stad_H=R19
.def index=R20
.def counter1=R21
.def counter2=R22
.def temp1_char=R23
.def temp2_char=R24
.def temp_ad1_L=R28 ; YL
.def temp_ad1_H=R29 ; YH
.def temp_ad2_L=R30 ; ZL
.def temp_ad2_H=R31 ; ZH
;---------SUBSTR_POS:
movw temp_ad1_L, str1_stad_L
movw temp_ad2_L, str2_stad_L
(1)
ld counter1, Y+
tst counter1
(ii)
breq er_str_len
(1)
ld counter2, Z+

tst counter2
breq er_str_len
sub counter1, counter2
brlo er_str_len
clt
ldi index, 1
inc counter1
char_comp:
(iii)
ld temp1_char, Y+
ld temp2_char, Z+
cp temp1_char, temp2_char
brne inc_check_stad
dec counter2
brne char_comp
ret
inc_check_stad:
(3)
subi counter1, 1
(i)
brcs not_found
(2)
inc index
movw temp_ad1_L, str1_stad_L
add temp_ad1_L, index
brcc contin1
inc temp_ad1_H
contin1:
movw temp_ad2_L, str2_stad_L
ld counter2, Z+
rjmp char_comp
not_found:
clr index
ret
er_str_len:
set
ret
;----- End of subroutine SUBSTR_POS ----.undef str1_stad_L
.undef str1_stad_H
.undef str2_stad_L
.undef str2_stad_H
.undef index
.undef counter1
.undef counter2
.undef temp1_char
.undef temp2_char
.undef temp_ad1_L
.undef temp_ad1_H
.undef temp_ad2_L
.undef temp_ad2_H
(ii)
(i)
(ii)

:
(1)
( ).
(2) index
-.

(3) counter1
.

)
1) AVR102 :BLOCK COPY ROUTINES (Site Atmel)

2) Move a block of data to a new location


: (
SRAM) . bytes (2-byte, block_len),
(orig_stad)
(new_stad).
:
- temp_stor: byte
- temp_stor2: temp_stor 16-bit
( )

SRAM 4 Kbytes (=$1000 bytes) ( SRAM


ATmega128) (
)
debugging:
(i) ? (
)
(ii)
?
(iii)

( ).

.

Start

block_len = 0
?

Yes

No

orig_stad <$100 or
orig_stad > $10FE or
new_stad < $100 or
new_stad > $10FE

(i)

Yes

End

No
(i) (ii)
orig_stad < new_stad
AND
orig_stad + block_len > new_stad

No
temp_stor := [orig_stad]
[new_stad] := temp_stor
orig_stad := orig_stad + 1
new_stad := new_stad + 1
block_len := block_len - 1
No

block_len = 0
?
Yes
End

Yes

:
;-------------------- Move a block of data to a new location -------------------;Title: MOV_BLOCK
;Purpose: Move a block of data to a new SRAM location, given a new starting address
;
! max size of block (potentially=65535) is limited by the type of the memory
;
! used for storing the data. Assuming use of internal SRAM (4KB =$1000 bytes),
;
! for both the initial and the final data storing,
;
! max size = $1000-2-d-a, when orig_stad>new_stad
;
! max size = ($1000-2-a)/2, when orig_stad<new_stad (in order not to overwrite)
;
2: Stack places used for the return address of the subroutine
;
d: absolute distance (in bytes) of transference
;
a: other possible SRAM used places
;Input Parameters:
;
block_len: number of bytes in the block - stored in R25:R24 - altered
;
orig_stad: original starting address of the block - stored in R27:R26 (X)
;
new_stad: new starting address of the block - stored in R29:R28 (Y)
;Other variables:
;
temp_stor: temporary storage of the currently transferred byte - stored in R16
;
temp_stor2: register used coupled with "temp_stor" in order to check for the
;
errors - stored in R17
;Exit: - (the block has been transferred to a new location)
;Errors:
;
ErrorA: orig_stad<$100 OR orig_stad+block_len>RAMEND-2 OR new_stad<$100 OR
;
new_stad+block_len>RAMEND-2 --> sets T flag, clears V flag
;
(inappropriate block bounds either for the old or the new location)
;
ErrorB: orig_stad<new_stad AND orig_stad+block_len>new_stad
;
--> sets both T and V flags
;
(overwriting part of the data before transferred)
;
Empty block : T=V=0
;Comments: ;-------------------.def block_len_L=R24
.def block_len_H=R25
.def orig_stad_L=R26 ; XL
.def orig_stad_H=R27 ; XH
.def new_stad_L=R28 ; YL
.def new_stad_H=R29 ; YH
.def temp_stor=R16
.def temp_stor2=R17
;---------MOV_BLOCK:
tst block_len_L
brne check_AA
tst block_len_H
breq skip_all
; block_len=0, nothing to move
check_AA:
tst orig_stad_H
(2)
breq inconsA
; orig_stad<$100
tst new_stad_H
(2)
breq inconsA
; new_stad<$100
movw temp_stor, new_stad_L
add temp_stor, block_len_L
adc temp_stor2, block_len_H
cpi temp_stor2, $10
; if temp_stor2:temp_stor>$10FE --> ErrorA

brlo new_ad_eligible
; temp_stor2<$10 --> no ErrorA for this check
(2)
brne inconsA
; temp_stor2>$10 --> ErrorA
(3)
cpi temp_stor, $FE
(2)
brsh inconsA
new_ad_eligible:
movw temp_stor, orig_stad_L
add temp_stor, block_len_L
adc temp_stor2, block_len_H
cpi temp_stor2, $10
; if temp_stor2:temp_stor>$10FE --> ErrorA
brlo eligible
; temp_stor2<$10 --> no ErrorA for this check
(2)
brne inconsA
; temp_stor2>$10 --> ErrorA
(3)
cpi temp_stor, $FE
brsh inconsA
(2)
eligible:
cp temp_stor2, new_stad_H ; checking if orig_stad+block_len>new_stad
(ii)
brlo error_free
brne check_BB
cp new_stad_L, temp_stor
brsh error_free
check_BB:
(ii)
cp new_stad_H, orig_stad_H ; checking if orig_stad<new_stad
brlo error_free
(2)
brne inconsB
cp new_stad_L, orig_stad_L
(2)
brsh inconsB
; it covers also the case when new_stad=orig_stad, which
; could be considered as a separate error, since there is no
; meaning to write the data at the same address it is read from,
; but it doesn't create any unpleasant consequences. There is no
; check if new_stad=orig_stad when orig_stad+block_len<=new_stad
error_free:
ld temp_stor, X+
st Y+, temp_stor
sbiw block_len_L, 1
tst block_len_L
brne error_free
tst block_len_H
brne error_free
clt
sev
ret
skip_all:
clt
clv
ret
inconsB:
set
sev
ret
inconsA:
set
clv
ret
;----- End of subroutine MOV_BLOCK ----.undef block_len_L
.undef block_len_H

.undef orig_stad_L
.undef orig_stad_H
.undef new_stad_L
.undef new_stad_H
.undef temp_stor
.undef temp_stor2
:
(1) 16-bit
bytes ( 65535),
SRAM. 4 KB SRAM,
:
- $1000-2-d-a, orig_stad>new_stad
- ($1000-2-a)/2, orig_stad<new_stad (
), :
2:
d: ( bytes)

a: SRAM
(2) . ( )
(ErrorA)
(ErrorB).
,
orig_stad
new_stad.
(3) $10FE ,
.
(SP),
.
SP ,
SP ( ISR).


.
(4) orig_stad new_stad ( byte
), block_len.
orig_stad new_stad .
(
).
.

Z3) Pointer to element in 2 Dimensional Array


: 1-byte
(elem_ad). (elem_row) (elem_col) ,
(numof_cols) (arst_ad).
(row major order,
, , ...),
256.
R1:R0
.
debugging:
?
?

Start

(i)
numof_cols = 0
?

Yes

No

(i)
arst_ad < $100
?

Yes

End

No
elem_ad = elem_row * numof_cols
elem_ad = elem_ad + elem_col

(i)
elem_ad < RAMEND - a
?
Yes
Flag correct result
End

No

(1)
(2)

(2)
(3)

;-------------------- Pointer to element in 2 Dimensional Array -------------------;Title: POINT_2D_AR


;Purpose: Calculation of the pointer to an element in an two-dimensional array of
;
one-byte elements, given the element's row and column number
;
! array is stored in row major order (first is stored all the elements of the
;
! first row, then the second's and so on
;
! only the number of array's columns is required; the maximum num of array
;
! elements is undefined (since the number of rows is unknown)
;Input Parameters:
;
arst_ad: array's starting address - stored in R19:R18 - unaltered
;
elem_row: element's row number - stored in R16 - unaltered
;
( 0 <= elem_row < numof_rows)
;
elem_col: element's column number - stored in R17 - unaltered
;
( 0 <= elem_col < numof_cols)
;
numof_cols: the number of columns in the array - stored in R20 - unaltered
;Other variables:
;
elem_ad: address of the specific element (output parameter) - stored in R29:R28
;"Special purpose" Registers used: R1, R0
;Exit: "elem_ad" holds a pointer to the specific element
;Errors:
;
ErrorA: numof_cols = 0 --> sets T flag, clears V flag
;
(it must be at least 1, in case we consider an 1-dimensional array)
;
ErrorB: arst_ad<$100 OR elem_ad>RAMEND-2 --> sets both T and V flags
;
(ineligible array starting address (too low) or ineligible element's address
;
(the array is too long to be stored in the SRAM, resulting in overwriting of
;
Stack and possibly SRAM pointer overrunning RAMEND)
;Comments:
;
- elem_ad = arst_ad+(elem_row*numof_cols+elem_col)
;-------------------.def arst_ad_L=R18
.def arst_ad_H=R19
.def elem_row=R16
.def elem_col=R17
.def numof_cols=R20
.def elem_ad_L=R28 ; YL
.def elem_ad_H=R29 ; YH
;---------POINT_2D_AR:
tst numof_cols
(i)
breq incons_A
; ErrorA
tst arst_ad_H
(i)
breq incons_B
; ErrorB: ineligible array_starting_address (too low)
mul elem_row, numof_cols
movw elem_ad_L, R0
add elem_ad_L, elem_col
brcc no_incr
inc elem_ad_H
no_incr:
add elem_ad_L, arst_ad_L
adc elem_ad_H, arst_ad_H
cpi elem_ad_H, $10
; if elem_ad>=$10FE --> ErrorB
(i)
brlo accept_result
; elem_ad_H<$10 --> no ErrorB
brne incons_B
; elem_ad_H>$10 --> ErrorB

cpi elem_ad_L, $FE


; since test_ad_H=$10 check also elem_ad_L
brlo accept_result
incons_B:
set
sev
ret
incons_A:
set
clv
ret
accept_result:
clt
clv
ret
;----- End of subroutine POINT_2D_AR ----.undef arst_ad_L
.undef arst_ad_H
.undef elem_row
.undef elem_col
.undef numof_cols
.undef elem_ad_L
.undef elem_ad_H
:
(1) numof_cols = 1.
(2) ,
( )
.
.
(3)
( )
.

You might also like