인텔리전트 기능 모듈/특수 기능 모듈은 사전에 모듈만의 특수한 용도로 정의된 버퍼 메모리 라는 것을 가지고 있습니다. 이런 특수한 용도로 정의된 버퍼 메모리를 CPU가 읽고 쓸 수 있도록 엑세스 기능의 명령어 입니다.
최근 이러한 버퍼 메모리 엑세스 명령을 사용하지 않고, 직접 유니트 지정 명령도 사용가능 합니다. 샘플 프로그램에서도 두가지 모두 예시 하였습니다.
1) 인텔리전트 기능 모듈 / 특수기능 모듈에서의 1워드 데이터 읽기 (FROM(P))
▶[FROM(P) n1 n2 (D) n3]
n1로 지정된 인텔리전트 기능 모듈 / 특수 기능 모듈 내의 버퍼 메모리 n2로 지정된 어드레스로부터 n3점의 워드의 데이터를 읽고, (D)로 지정된 디바이스 이후에 저장
2) 인텔리전트 기능 모듈/특수 기능 모듈에서의 2워드 데이터읽기(DFRO(P))
▶[DFRO(P) n1 n2 (D) n3]
n1로 지정된 인텔리전트 기능 모듈/특수기능 모듈 내의 버퍼메모리 n2로 지정된 어드레스로부터 (n3*2)점의 워드 데이터를 읽고, (D)로 지정된 디바이스 이후에 저장
3) 인텔리전트 기능 모듈/특수 기능 모듈로의 1워드 데이터쓰기 (TO(P))
▶[TO(P) n1 n2 (S) n3]
(S)로 지정된 디바이스로 부터 n3점의 데이터를 n1로 지정된 인텔리전트 기능 모듈/특수 기능 모듈 내의 버퍼 메모리 n2 로 지정된 어드레스 이후에 씁니다.
인텔리전트 기능 모듈/특수 기능 모듈의 버퍼데이터 읽기, 쓰기명령어 FROM,DFRO,TO,DTO는 버퍼메모리의 주소를 H####, K#### 등으로 16진수, 10진수의 표현이 가능합니다. 버퍼메모리 직접지정 명령 U##/G####의 경우에는 10진수 표현만 가능합니다.
(S)로 지정된 16비트 데이터를 (D)로 지정된 데이터 테이블에 저장합니다. (D)에 테이블에 저장되어 있는 데이터 수를 저장하고, (D)+1 이후에 (S)로 지정된 데이터를 순차적으로 저장해갑니다. FIFW명령을 처음 실행하는 경우에는 (D)로 지정된 디바이스의 값을 클리어 하십시오 데이터 테이블에 입력한 데이터 수와 데이터 테이블 범위는 사용자가 관리하십시오.
2) 테이블에서의 선입 데이터 읽기(FIFR(P))
▶[FIFR(P) (S) (D)]
(D)로 지정된 테이블로부터 가장 먼저 읽혀진 데이터(D+1) 가 (S)로 지정된 디바이스에 저장됩니다. FIFR명령 실행 후에는 데이터 테이블의 데이터가 1개씩 시프트 됩니다. (D)에 저장되어 있는 값이 0일 때는, FIFR명령을 실행하지 않도록 사용자가 인터록 프로그램을 추가하십시오.
3) 데이터 테이블에서의 후입 데이터 읽기 (FPOP(P))
▶[FPOP(P) (S) (D)]
(D)로 지정된 테이블의 마지막에 저장되어 있는 데이터를 (S)로 지정된 디바이스에 저장합니다. FPOP명령 실행후에는 FPOP명령으로 읽은 데이터를 저장하고 있던 디바이스가 0으로 됩니다. (D)에 저장되어 있는 값이 0일 때는, FPOP 명령을 실행하지 않도록 사용자가 인터록 프로그램을 추가하십시오.
FOR ~ NEXT 명령간의 처리를 n회 실행하게 되면 무조건 NEXT명령의 다음 스텝을 처리합니다. n은 1~32767을 지정할 수 있습니다. -32768~0을 지정했을 때는 n=1과 동일한 처리를 합니다. FOR ~ NEXT 명령 간의 처리를 하지 않을 때는 CJ, SCJ, 명령으로 점프시키십시오. FOR의 네스팅은 16중까지 가능합니다.
다음의 경우에는 연산에러가 되며, 에러플래그(SM0)가 ON하고, 에러 코드가 SD0에 저장됩니다. FOR명령을 실행 후, NEXT명령을 실행하기 전에 END(FEND)명령을 실행했을 때 (에러코드: 4200) FOR명령을 실행하기 전에 NEXT 명령을 실행했을 때 (에러코드:4201) FOR명령의 네스팅을 실행하는 경우, 17번째 네스팅을 실행했을 때(에러코드:4202)
▶[NEXT]
FOR~NEXT 명령간의 처리에서 n에서 지정한 횟수만큼 FOR명령줄로 되돌려(점프) 줍니다. FOR~NEXT 명령에서 FOR의 네스팅에서 같은 수 만큼 1:1로 NEXT문이 있어야 합니다.
2) FOR~NEXT 강제종료(BREAK(P))
▶[BREAK(P) (D) pn]
FOR~NEXT명령에 의한 반복처리를 강제적으로 종료하고, Pn으로 지정된 포인터로 실행위치를 이동합니다. Pn에는 동일 프로그램 파일 내의 포인터만 지정할 수 있습니다. Pn에 다른 프로그램 파일 내의 포인터를 지정한 경우는 연산 에러가 됩니다. (D)에는 강제종료한 시점의 FOR~NEXT 명령에서의 반복처리 실행 횟수의 잔여수를 저장합니다. 단, 반복처리의 잔여수에는 BREAK 명령 실행시의 횟수도 포함됩니다. BREAK명령은 FOR~NEXT 명령 사이에 서만 사용할 수 있습니다. BREAK 명령은 하나의 네스팅에 대해서만 사용할 수 있습니다. 다중네스팅을 강제 종료 시킬 경우는 네스팅만큼의 BREAK 명령을 실행하십시오
3) 서브루틴 프로그램 호출(CALL(P))
▶[CALL(P) Pn]
CALL(P)명령을 실행하면 Pn으로 지정된 포인터의 서브루틴 프로그램을 실행합니다. CALL(P)명령은 동일 프로그램 파일 내의 포인터로 지정한 서브루틴 프로그램과 공통 포인터로 지정한 서브루틴 프로그램을 실행할 수 있습니다.
서브루틴(SubRoutine) - 프로그래밍시 매크로(macro)기능을 자주 사용한다. 매크로란 반복되어 자주 사용되는 명령어를 묶어서 하나의 이름으로 만드는 것을 말한다. C언어 등의 프로그래밍 언어를 이용하여 프로그래밍시 매크로를 사용하게 되면 컴파일시에 해당 매크로를 사용하는 부분은 매크로의 원문으로 모두 교체되게 되므로 소스코드의 크기가 커지고 그만큼 메모리의 점유율이 높아지는 단점이 있다.
이런 매크로의 단점을 극복하고 반복되는 것을 한번만 사용하여 메모리 사용을 최대한 줄이도록 고안된 것이 서브루틴(Sub-routine)이다. 이는 메인루틴(Main-routine)의 대비되는 개념으로 혼자 쓰이는 것이 아닌 메인루틴에 붙어 보조하는 역할을 한다. 반복되는 특정한 기능을 모아 놓은 이름을 붙여 놓았다는 것은 매크로와 같지만 프로그램 흐름이 메인루틴에 있지 않고, 별도의 공간에 한번만 생긴다는 것이 다르다. 아래 예를 통해서 서브루틴에 대한 개념을 정확히 알아보도록 하자.
▶[CALL(P) Pn(S1)~(S5)]
CALL(P) 명령을 실행하면 Pn으로 지정된 포인터의 서브루틴 프로그램을 실행합니다. CALL(P) 명령은 동일 프로그램 파일 내의 포인터로 지정한 서브루틴 프로그램과 공통 포인터로 지정한 서브루틴 프로그램을 실행 할 수 있습니다. 서브루틴 프로그램에서 기능(Function) 디바이스(FX,FY,FD)를 사용하는 경우는 (S1)~(S5) 기능 디바이스에 대응하는 디바이스를 지정합니다. (S1)~(S5)로 지정된 디바이스 내용은 서브루틴 프로그램 실행 전에 비트 데이터의 내용이 FX에, 워드데이터의 내용이 FD에 전송됩니다. CALL(P) 명령에서는 (S1)~(S5)까지 사용 가능합니다. 서브루틴 프로그램에서 사용하는 기능 디바이스의 수와 CALL(P) 명령의 인수는 동 수로 할 필요가 있습니다. 또한 기능 디바이스와 CALL(P)의 인수 종류는 동일하게 하십시오. CALL(P) 명령에서 인수로 지정한 디바이스 번호는 중복되지 않도록 하십시오. 중복되는 경우에는 정상적으로 연산을 할 수 없습니다. CALL(P) 명령에서 인수로 지정한 워드 디바이스(4워드)를 서브 루틴 프로그램에서 사용하지 마십시오. 사용하게 되면 정상적인 연산을 할 수 없습니다. CALL(P)명령의 네스팅은 16중까지 가능합니다. 단 네스팅의 16중은 CALL(P), FCALL(P), ECALL(P), EFCALL(P) 명령의 합계입니다. 서브 루틴 프로그램 내에서 ON시킨 디바이스는 서브 루틴 프로그램의 비 실행시에서도 유지됩니다. 서브 루틴 프로그램 실행시에 ON시킨 디바이스는 FCALL(P)명령으로 OFF시킬 수 있습니다.
4) 서브루틴 프로그램에서의 리턴(RET)
▶[RET]
서브루틴 프로그램의 종료를 실행합니다. RET 명령을 실행하면 서브 루틴 프로그램을 호출한 CALL(P), FCALL(P), ECALL(P), EFCALL(P) 명령의 다음 스텝으로 복귀합니다. 다음의 경우에 연산 에러가 되며, 에러플래그(SM0)가 ON하고, 에러코드가 SD0 에 저장됩니다. CALL(P)명령 실행 후, RET 명령을 실행하기 전에 END, FEND, GOEND, STOP 명령을 실행했을 때(에러코드4211) CAPP(P) 명령을 실행하기 전에 RET 명령을 실행했을 때 (에러코드: 4212)
이것의 결과를 보면 pnum의 실질적인 값은 num의 주소이며, num의 값을 가리키고 있음
여기서 &연산자는 &오른쪽에 오는 피연산자의 주소값을 반환하는 연산자이다.
그리고 포인터도 가리키고자하는 변수의 자료형에 따라 포인터변수도 그에 맞춰 다르게 선언한다.
ex) duble num;
double *pnum; // double형 포인터 변수 pnum
char cha;
char *pcha; // char형 포인터 변수 pcha
사실 주소값은 동일한 시스템에서 그 크기가 동일하며, 모두 정수의 형태를 띈다. 하지만 모두 다 똑같이 int형으로 포인터 변수를 선언한다면, 다른 사용자나 자신 그리고 시스템은 해당 포인터 변수가 무엇을 가리키는건지 알기 힘듬.
그래서 *이 붙은 자료형은 포인터 형이라 한다. 물론 포인터도 값을 저장하는 변수이기에 자료형의 범주에 포함된다.
또 하나의 사실은 *의 위치는 크게 상관이 없다.
ex) int* pnum;
int *pnum;
int * pnum;
위처럼 프로그래머 마음대로 골라 쓰면됨.
*연산자는 포인터가 가리키는 메모리공간에 접근할 때 사용되는 연산자이며, 포인터 변수를 이용해 포인터 변수가 가리키는 변수의 값을 바꿀 수도 있다.
널 포인터(NULL Pointer)
포인터를 선언만 하고, 초기화해주지 않으면, 내부에는 쓰레기값으로 채워지는데, 이는 그 포인터 변수가 어디를 가리킬지 아무도 알 수 없다. 설령 포인터가 가리키는 주소가 메모리상에서 아주 중요한 공간이라도 모를 것이다. 거기다가 아래의 코드처럼 *연산으로 임의의 수를 저장하면, 프로그램에 치명적인 결과를 가지고 올 수 있다.
그렇다면 초기값을 대충 1234로 해야하나? 이것도 안된다. 왜냐하면 이 1234번지가 메모리의 어디에 있는지 알 수 없다. 고로 쓰레기 값으로 채우는 것과 다를 바없다. 그래서 NULL값을 이용하는 것이다.
이 둘이 의미하는 바는 같다 왜 0과 NULL이 같은 의미를 지니냐면 0은 아스키코드에서 NULL이기 때문이다. 그리고 0이라는 숫자가 들어가면 *pnum1이 0번지를 가리키진 않는다. 여기서 0(NULL)의 의미는 해당 포인터 변수는 아무것도 가리키고 있지 않다고 할 수 있다.
(S)로 지정된 디바이스부터 n점의 16비트 BIN데이터에서 최대값을 검색하여, (D)로 지정된 디바이스에 저장 (S)로 지정된 디바이스부터 검색하여, 처음에 검출한 최대값이 저장되어 있는 디바이스 번호가 (S)에서 몇번째 점인지를 (D)+1에 저장하고, 최대값의 개수를 (D)+2에 저장합니다.
▶[DMAX(P) (S) (D) n]
(S)로 지정된 디바이스부터 n점의 32비트 BIN데이터에서 최대값을 검색하여, (D), (D)+1로 지정된 디바이스에 저장 (S)로 지정된 디바이스부터 검색하여, 처음에 검출한 최대값이 저장되어 있는 디바이스 번호가 (S)에서 몇번째 점인지를 (D)+2 에 저장하고, 최대값의 개수를 (D)+3에 저장
11) 16비트/32비트 데이터 최소값 검색(MIN(P), DMIN(P))
▶[MIN(P) (S) (D) n]
(S)로 지정된 디바이스부터 n점의 16비트 BIN데이터에서 최소값을 검색하여 (D)로 지정된 디바이스에 저장 (S)로 지정된 디바이스부터 검색하여, 처음에 검출한 최소값이 저장되어 있는 디바이스 번호가 (S)에서 몇번째 점인지를 (D)+1에 저장하고, 최소값의 개수를 (D)+2에 저장
▶[DMIN(P) (S) (D) n]
(S)로 지정된 디바이스부터 n점의 32비트 BIN데이터에서 최소값을 검색하여, (D), (D)+1로 지정된 디바이스에 저장 (S)로 지정된 디바이스부터 검색하여, 처음에 검출한 최소값이 저장되어 있는 디바이스 번호가 (S)에서 몇번째 점인지를, (D)+2에 저장하고, 최소값의 개수를 (D)+3에 저장
12) 16비트/32비트 데이터 소트(SORT(T), DSORT(P))
▶[SORT(P) (S1)n (S2) (D1) (D2)]
(S1)부터 n점분의 BIN 16비트 데이터를 오름차순/내림차순 으로 소트(정렬)합니다. 소트순서는 SM703의 ON/OFF로서 지정 SM703이 OFF시 : 오름차순으로 소트 SM703이 ON시 : 내림차순으로 소트 SORT 명령에 의한 소트는 몇 스캔이 필요합니다. 실행 완료까지의 스캔 횟수는 소트 실행완료까지의 최대 실행 횟수를 (S2)로 지정된 1회의 실행에서 비교하는 데이터 수로 나눈 값이 됩니다. (소수점 이하는 올림이 됩니다) (S2)의 값을 크게하면 소트 완료까지의 스캔 횟수는 적어지지만, 스캔 타임은 연장됩니다. 소트의 실행 완료까지의 최대 실행 횟수는 다음식으로 산출 가능하다. 실행완료까지의 최대 실행 횟수 = (n)* (n-1) / 2 / (S2)[회] 예를 들면 n=10, (S2)=1의 경우에는 10* (10-1) / 2 / 1 =45(회) 걸립니다. 이 때, (S2)=2 로 하면 소트 완료까지에 45 / 2 = 22.5 > 23 [스캔] 이 걸린다. (D1)로 지정된 디바이스 비트(완료 디바이스)는 SORT명령 실행 시작에서 OFF하고 소트가 완료하면 ON합니다. 소트 완료 후, (D1)로 지정된 디바이스 비트는 ON상태가 유지되기 때문에, 필요에 따라 사용자가 OFF하십시오 (D2)로 지정된 디바이스에 2점은 SORT명령 실행시에 시스템이 사용합니다. (D2)로 지정된 디바이스에서 2점은 사용자가 변경하지 마십시오. 소트 실행 중에 n을 변경했을 경우에는 변경 후의 소트 데이터를 수로 소트를 합니다. 소트 실행 중에 지령을 OFF 했을 때에는 소트를 중단합니다. 다시 지령을 ON했을 경우에는 소트를 처음부터 다시 합니다.
▶[DSORT(P) (S1)n (S2) (D1) (D2)]
(S1)부터 n점분의 BIN 32비트 데이터를 오름차순/내림차순으로 소트(정렬)합니다. 소트 순서는 SM703의 ON/OFF로써 지정합니다. SM703이 OFF시 : 오름차순으로 소트 SM703이 ON시 : 내림차순으로 소트 DSORT 명령에 의한 소트는 몇 스캔이 필요합니다. 실행 완료까지의 스캔 횟수는 소트 실행완료까지의 최대 실행 횟수를 (S2)로 지정된 1회의 실행에서 비교하는 데이터 수로 나눈 값이 됩니다. (소수점이하는 올림이 됩니다) (S2)의 값을 크게하면 소트 완료까지의 스캔 횟수는 적어지지만, 스캔 타임은 연장됩니다. 소트의 실행 완료까지의 최대 실행 횟수는 다음식으로 산출 하십시오 실행완료까지의 최대 실행 횟수 = (n)* (n-1)/2/(S2)[회] 예를 들면 n=10, (S2)=1의 경우에는 10* (10-1) /2 /1 =45(회) 걸립니다. 이 때, (S2) =2로 하면 소트 완료까지에 45/2 = 22.5 > 23[스캔]이 걸립니다. (D1)로 지정된 디바이스 비트(완료디바이스)는 DSORT 명령 실행 시작에서 OFF하고 소트가 완료하면 ON합니다 소트 완료 후, (D1)로 지정된 디바이스 비트는 ON상태가 유지되기 때문에, 필요에 따라 사용자가 OFF하십시오 (D2)로 지정된 디바이스에서 2점은 DSORT 명령 실행시에 시스템이 사용합니다. (D2)로 지정된 디바이스에서 2점은 사용자가 변경하지 마십시오. 소트 실행 중에 n점을 변경 했을 경우에는 변경 후의 소트 데이터를 수로 소트를 합니다. 소트 실행 중에 지령을 OFF했을 때에는 소트를 중단합니다. 다시 지령을 ON했을 경우에는 소트를 처음부터 다시 합니다.
13) 16비트 데이터 한계값 산출(WSUM(P), DWSUM(P))
▶[WSUM(P) (S) (D) n]
(S)지정된 디바이스부터 n점의 16비트 BIN데이터를 모두 가산하여, (D)로 지정된 디바이스에 저장합니다.
▶[DWSUM(P) (S) (D) n]
(S)지정된 디바이스부터 n점의 32비트 BIN데이터를 모두 가산하여, (D)로 지정된 디바이스에 저장 디바이스를 n점의 32비트 BIN데이터로 처리 하기 때문에, WSUM(P)과 DWSUM(P) 의 계산결과는 다르게 됩니다.
(S)로 지정된 16비트 데이터의 하위 n자리(1자리 4비트)분의 데이터를 (D)로 지정된 디바이스부터 n점 분의 하위 4비트에저장 (D)로 지정된 디바이스부터 n점분의 상위 12비트는 0으로 됩니다. n은 1~4를 지정할 수 있습니다. n=0일 때는 무처리 되며, (D)의 디바이스부터 n점분의 내용은 변화하지 않습니다.
7) 16비트 데이터의 4비트 결합 (UNI(P))
▶[UNI(P) (S) (D) n]
(S)로 지정된 디바이스부터 n점분의 16비트 데이터의 하위 4비트를 (D)로 지정된 16비트 디바이스에 결합 (D)로 지정된 디바이스의 상위(4-n)자리의 비트는 0으로 됩니다. n은 1~4를 지정할 수 있습니다. n=0 일때는 무처리되며, (D)의 디바이스의 내용은 변화하지 않습니다.
8) 임의 데이터의 비트 분리, 결합(NDIS(P), NUNI(P))
▶[NDIS(P) (S1) (D) (S2)]
(S1)로 지정된 디바이스 번호 이후에 저장되어 있는 데이터의 각 비트를 (S2)로 지정된 비트만큼씩 분리하여, (D)로 지정된 디바이스 번호 이후에 저장합니다. (S2)로 지정된 분리 비트를 1~16비트의 범위에서 지정할 수 있습니다. (S2)에 의한 지정 디바이스 번호에서 0을 저장한 번호까지를 분리 비트수로서 처리
▶[NUNI(P) (S1) (D) (S2)]
(S1)로 지정된 다바이스 번호 이후에 저장되어 있는 데이터의 각 비트를 (S2)로 지정된 비트만큼씩 결합하여, (D)로 지정된 다바이스 번호 이후에 저장한다. (S2)로 지정된 결합비트를 1~16비트의 범위에서 지정할 수 있다. (S2)에 의한 지정 디바이스 번호에서 0을 저장한 디바이스 번호까지를 결합 비트 수로써 처리합니다.
9) 바이트 단위 데이터분리, 결합(WTOB(P), BTOW(P))
▶[WTOB(P) (S) (D) n]
(S)로 지정된 디바이스 번호 이후에 저장되어 있는 16비트 데이터를 n바이트로 분리하여, (D)로 지정된 디바이스 번호 이후에 저장, 예를 들면 n=5의 경우는 (S)~(S+2)의 하위 8비트까지의 데이터를 (D) ~(D+4)에 저장 n으로 바이트 수를 설정함으로써 (S)로 지정된 16비트 데이터의 범위 및 (D)로 지정된 바이트 데이터를 저장하는 디바이스의 범위가 자동으로 결정됩니다. n에 지정된 바이트 수가 0인 경우는 처리를 실행하지 않습니다. (D)로 지정된 바이트 데이터 저장\ 디바이스의 상위 8비트에는 자동적으로 00H가 저장됩니다.
▶[BTOW(P) (S) (D) n]
(S)로 지정된 디바이스 번호 이후의 n워드분의 16비트 데이터의 하위 8비트를 워드 단위로 결합하여, (D)로 지정된 디바이스 번호 이후에 저장, (S)로 지정된 디바이스 번호 이후의 n워드 데이터의 상위 8바이트는 무시됩니다. 또한 n이 홀수인 경우는 n번째 바이트의 데이터를 저장한 디바이스의 상위 8비트에 0을 저장합니다. 예를 들면 n=5의 경우는 (S)~ (S+4)의 하위 8비트의 데이터를 결합하여 (D)~(D+2)에 저장 n으로 바이트 수를 설정함으로써, (S)로 지정된 바이트 데이터의 범위 및 (D)로 지정된 결합 데이터 저장 디바이스의 범위가 자동적으로 정해집니다. n으로 지정된 디바이스 수가 0인 경우는 무처리 됩니다. (S)로 지정된 바이트 데이터 저장 디바이스의 상위 8비트를 무시하고, 하위 8비트가 대상이 됩니다. 결합한 데이터가 저장되어 있는 디바이스의 범위 (S)~(S+n)와 결합된 데이터를 저장하는 디바이스의 범위 (D)~(D+n)가 중복하는 경우 라도 정상으로 처리합니다.
[DIS(P)], [UNI(P)], [NDIS(P)], [NUNI(P)], [WTOB(P)], [BTOW(P)] 의 명령어는 상위 호스트와의 통신, MES, CIM, PC등의 통신 및 각종 이종기기, 드라이버와의 통신등에서 이루어지는 DATA교신시 DATA의 포맷변경, 비트/바이트/워드 변환등에 사용합니다.